【问题标题】:Calling a generic method with interface instances使用接口实例调用泛型方法
【发布时间】:2015-10-29 08:35:33
【问题描述】:

作为this one的后续问题

public interface IFeature  {  }

public class FeatureA : IFeature { }

IFeature a = new FeatureA();
Activate(a);

private static void Activate<TFeature>(TFeature featureDefinition) where TFeature : IFeature
{

}

我不明白,一旦将 FeatureA 转换为 IFeature,泛型方法将始终将 IFeature 作为类型参数。

我们的服务为我们提供了列表功能 (List&lt;IFeature&gt;)。如果我们想遍历这些特征,在泛型方法中传递每个特征,我想除了

之外没有其他方法可以在泛型方法中获取具体类型

由于反射非常昂贵,我想使用动态转换。以这种方式调用该方法有什么缺点吗?这样做的时候不知何故我觉得很脏:-)

【问题讨论】:

  • dynamic 只会在幕后使用反射。
  • 为什么要创建一个 generic 方法,因为它的实现涉及到参数的实际类型?也许动态调度会是更好的方法 (stackoverflow.com/q/14840931)。此外,您可以使用isasGetType() 确定TFeature 的实际类型。
  • 您可以使用访问者模式来完成您的任务

标签: c# generics dynamic reflection interface


【解决方案1】:

假设您可以修改代码库,您可以按如下方式使用访问者模式。否则,使用动态。

public interface IFeature
{
    void Accept(Visitior visitor);
}

public class FeatureA : IFeature
{
    public void Accept(Visitior visitor)
    {
        visitor.Visit(this);
    }
}

public class FeatureB : IFeature
{
    public void Accept(Visitior visitor)
    {
        visitor.Visit(this);
    }
}

public class Visitior
{
    public void Visit<TFeature>(TFeature feature) where TFeature : IFeature
    {
        Console.WriteLine(typeof(TFeature) == feature.GetType());//True
    }
}

static void Main(string[] args)
{
    List<IFeature> features = new List<IFeature>
    {
         new FeatureA(),
         new FeatureB()
    };

    Visitior visitor = new Visitior();
    foreach (var item in features)
    {
        item.Accept(visitor);
    }
}

【讨论】:

  • 很好的答案 - 访问者模式的一个很好的用例
【解决方案2】:

您可以使用 typeof 获取泛型/(非泛型)类型的类型对象:

    public static T Parse<T>(String value)
    {
        object result = default(T);
        var typeT = typeof (T);
        if (typeT == typeof(Guid))
        {
            result = new Guid(value);
        }
        else if (typeT == typeof(TimeSpan))
        {
            result = TimeSpan.Parse(value);
        }
        else
        {
            result = Convert.ChangeType(value, typeT);
        }
        return (T)result;
    }

我的简单方法返回 T。这是一个关键点。它必须是通用的,以允许开发人员指定返回类型。如果方法不返回泛型并且只接受一个,那么有几个原因使它成为泛型。避免对方法参数进行装箱/拆箱操作,或者解决方法采用不同类型的参数时的情况,这些参数不是从公共基类/接口继承的。这不是你的情况。因此,您的代码中的方法不必是通用的。只需将您的参数输入为 IFeature 并使用 is/as/GetType():

private static void Activate(IFeature feature) 
{
   if (feature is FeatureImplementationA)
   {
      //Do something...
   }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 2018-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多