繁体   English   中英

如何使用反射将“ MyTypes”的每个列表传递给约束为T:MyType的通用方法?

[英]How can I use reflection to pass each list of “MyTypes” to a generic method with a constraint of T:MyType?

如何使用反射将每个“ MyTypes”列表传递给具有T:MyDataObject约束的通用方法?

public interface IAllMyTypes
{
    List<FirstType> MyType1 { get; set; }
    List<SecondType> MyType2 { get; set; }
    List<ThirdType> MyType3 { get; set; }
}

FirstType,SecondType和ThirdType从MyDataObject继承(如下所示),但是具有不同的属性。

public class FirstType : MyDataObject
{
  //various properties
}   

我一直无法将数据传递到具有此签名的方法中:

void DoSomething<T>(IEnumerable<T> enumerable) where T : MyDataObject;

错误是“无法推断类型参数”。

这是我失败的尝试:

public void DoSomethingWithAllMyTypes(IAllMyTypes allMyTypes)
{
    foreach (PropertyInfo propertyInfo in allMyTypes.GetType().GetProperties())
    {
        var x = propertyInfo.GetValue(allMyTypes) as IList;//im not sure what to do here
        if(x==null) throw new Exception("still wrong");

        DoSomething(x);
    }
}   

如果我直接提供如下所示的属性,则DoSomething(..)中的所有代码都可以正常工作:

public void DoSomethingWithAllMyTypes(IAllMyTypes allMyTypes)
{
    DoSomething(allMyTypes.MyType1);
    DoSomething(allMyTypes.MyType2);
    DoSomething(allMyTypes.MyType3);
}

如果要使用反射,则也可以使用反射来调用辅助方法:

您将必须获取通用方法的MethodInfo并创建一个通用方法反射句柄以实际Invoke该方法。 在这种情况下,需要在运行时获取通用方法的类型T

public void DoSomethingWithAllMyTypes(IAllMyTypes allMyTypes)
{
    var method = this.GetType().GetMethod("DoSomething", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
    foreach (PropertyInfo propertyInfo in allMyTypes.GetType().GetProperties())
    {
        var x = propertyInfo.GetValue(allMyTypes, null);
        if(x==null) throw new Exception("still wrong");

        // obtain the type from the property - other techniques can be used here.
        var genericMethod = method.MakeGenericMethod(new[] {propertyInfo.PropertyType.GetGenericArguments()[0]})
        //execute the generic helper
        genericMethod.Invoke(this, new[]{x});
    }
} 

public void DoSomething<T>(IList<T> list) where T : MyDataObject {

}

我正在努力寻找一个案例,在这种情况下,您需要以与过去相同的方式来构造数据,而又不会使事情复杂化。 如果您发现合法案件,请发表评论,我将更新答案以反映您的需求。

你可以用你的基类开始,使它抽象,把一个抽象的方法,它DoSomething

public abstract class MyDataObject{
  public string SomeSharedProperty{get;set;}
  protected abstract DoSomething(); 
}

public class FirstType: MyDataObject{ 
  protected override DoSomething(){
    Console.WriteLine(SomeSharedProperty);
  }
}


public class Consumer{
  public void DoSomethingWithAllMyTypes(List<MyDataObject> source)
  {
    source.ForEach(x=>x.DoSomething());
  }
}

您可以使用Linq方法调用Cast<T>将列表转换为正确的类型

public void DoSomethingWithAllMyTypes(IAllMyTypes allMyTypes)
{
    foreach (PropertyInfo propertyInfo in allMyTypes.GetType().GetProperties())
    {
        var x = propertyInfo.GetValue(allMyTypes) as IEnumerable
        if(x==null) throw new Exception("still wrong");

        DoSomething(x.Cast<MyDataObject>());
    }
}  

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM