Calling a generic method with interface instances

2019-06-18 22:58发布

As a followup question to 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
{

}

I undestand, that once the FeatureA is casted to IFeature the generic method will always get IFeature as type parameter.

We have a service with provides us with a list features (List<IFeature>). If we want to iterate over those features, passing each in the generic method, I guess there is no way to get the concrete type in the generic method other than

Since reflection is very costly, I would like to use the dynamic cast. Is there any downside to call the method that way? Somehow I feel dirty when doing that :-)

2条回答
兄弟一词,经得起流年.
2楼-- · 2019-06-18 23:46

You can use visitor pattern as follows assuming that you can modify your codebase. Otherwise, use dynamic.

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);
    }
}
查看更多
迷人小祖宗
3楼-- · 2019-06-18 23:58

You can obtain the type object for generic/(not generic) type using 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;
    }

My simple method returns T. And this is a key point. It must be generic to allow developer to specify return type. If method doesn't return generic and only accepts one then there are several reasons to make it generic. To avoid box/unbox operations on method arguments or to tackle with situation when method takes argument of different types which are not inherited from common base class/interface. And it's not your case. So the method in your code haven't to be generic. Just type you argument as IFeature and use is/as/GetType():

private static void Activate(IFeature feature) 
{
   if (feature is FeatureImplementationA)
   {
      //Do something...
   }
}
查看更多
登录 后发表回答