Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我如何使用反射传递每个列表的;“我的类型”;到约束为T:MyType的泛型方法?_C#_Generics_Reflection - Fatal编程技术网

C# 我如何使用反射传递每个列表的;“我的类型”;到约束为T:MyType的泛型方法?

C# 我如何使用反射传递每个列表的;“我的类型”;到约束为T:MyType的泛型方法?,c#,generics,reflection,C#,Generics,Reflection,如何使用反射将每个“MyTypes”列表传递给约束为T:MyDataObject的泛型方法 public interface IAllMyTypes { List<FirstType> MyType1 { get; set; } List<SecondType> MyType2 { get; set; } List<ThirdType> MyType3 { get; set; } } 我无法将数据传递到具有此签名的方法: void D

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

public interface IAllMyTypes
{
    List<FirstType> MyType1 { get; set; }
    List<SecondType> MyType2 { get; set; }
    List<ThirdType> MyType3 { get; set; }
}
我无法将数据传递到具有此签名的方法:

void DoSomething<T>(IEnumerable<T> enumerable) where T : MyDataObject;
如果我直接提供如下属性,DoSomething(..)中的所有代码都能正常工作:

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

我正在努力寻找一种情况,在这种情况下,您需要按照您的方式构建数据,而不会使事情过于复杂。如果你发现了一个合法的案例,请发表评论,我会更新我的答案以反映你的需求

您可以从基类开始,将其抽象化,并在其中放入一个抽象方法
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());
  }
}
公共抽象类MyDataObject{
公共字符串SomeSharedProperty{get;set;}
受保护的抽象剂量学();
}
公共类FirstType:MyDataObject{
受保护的覆盖剂量计(){
Console.WriteLine(某些共享属性);
}
}
公共类消费者{
public void DoSomethingWithAllMyTypes(列表源)
{
source.ForEach(x=>x.DoSomething());
}
}

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

您必须获得泛型方法的
MethodInfo
,并创建泛型方法反射句柄以实际调用该方法。在这种情况下,需要在运行时获取泛型方法的类型
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 {

}
public void DoSomethingWithAllMyTypes(IAllMyTypes allMyTypes)
{
var method=this.GetType().GetMethod(“DoSomething”,BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
foreach(allMyTypes.GetType().GetProperties()中的PropertyInfo PropertyInfo)
{
var x=propertyInfo.GetValue(allMyTypes,null);
如果(x==null)抛出新异常(“仍然错误”);
//从属性获取类型-这里可以使用其他技术。
var genericMethod=method.MakeGenericMethod(新[]{propertyInfo.PropertyType.GetGenericArguments()[0]})
//执行泛型助手
Invoke(this,new[]{x});
}
} 
公共void DoSomething(IList列表),其中T:MyDataObject{
}

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

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>());
    }
}  
public void DoSomethingWithAllMyTypes(IAllMyTypes allMyTypes)
{
foreach(allMyTypes.GetType().GetProperties()中的PropertyInfo PropertyInfo)
{
var x=propertyInfo.GetValue(allMyTypes)作为IEnumerable
如果(x==null)抛出新异常(“仍然错误”);
DoSomething(x.Cast());
}
}  

<代码> > IIST < /COD>(非泛型)会很好。如果你做这些步骤的唯一原因是调用多个次数,那么考虑一个数据结构,如列表类型列表=新列表{Type(A),Type of(B),Type(C)};而不是你的我的类型。然后你可以迭代它,并更改DoSomething的函数签名。它应该是
allMyTypes.GetType().GetProperties()
还是
typeof(IAllMyTypes)。GetProperties()
将它放入并第一次使用!就是这样。非常感谢。我不确定这是否需要一个全新的问题,但我在其他地方用DoSomethingElse(IEnumerable list)方法做了类似的事情,我试图传递到前面的同一个DoSomething方法,但是,我得到了一个错误:“System.Collections.Generic.list
1[MyDataObject]类型的对象”“无法转换为类型”System.Collections.Generic.IEnumerable
1[FirstType]”。我试图修改上面的例子,但显然我有点错误。这不起作用,因为DoSomething中的T类型是“MyDataObject”,而不是真正的类型,如FirstType、SecondType、,etc导致代码中的反射只能访问MyDataObject的成员。@user2565663不,这不是真的,反射不会在意,因为GetType将返回真的类型。我已经运行了这个示例,但实际情况并非如此。你能分享一些代码来证明你说的是真的吗?当我在DoSomething中时,T是一个MyDataObject,我不知道如何才能在它上键入并获得不同的类型。@user2565663 inside
DoSomething(T value)
typeof(T)
将返回MyDataObject,但是
value。GetType()
将返回值的真正类型,无论您如何强制转换它。例如,尝试在变量
x
中拥有一个类型为
FirstType
的对象,然后调用
DoSomething((MyDataObject)x)
@user2565663如果您使用的是反射,那么您真的不应该使用泛型,泛型实际上适用于基于非反射的方法,在这种方法中,您需要返回原始类型,或者在编译时需要绝对类型。如果您使DoSomething非泛型,接受类型为
MyDataObject
的对象,并在值上使用GetType(在检查其非null之后),那么您的代码也可以正常工作
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 {

}
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>());
    }
}