c# - 如何从对象类型定义泛型类型?

标签 c# generics extension-methods

我有一个扩展方法:

public static List<object> ToModelViewObjectList<ModelViewType>(this IEnumerable<object> source)
{

    List<ModelViewType> destinationList = new List<ModelViewType>();

    PropertyInfo[] ModelViewProperties = typeof(ModelViewType).GetProperties();
    foreach (var sourceElement in source)
    {
        object destElement = Activator.CreateInstance<ModelViewType>();
        foreach (PropertyInfo sourceProperty in sourceElement.GetType().GetProperties())
        {

            if (ModelViewProperties.Select(m => m.Name).Contains(sourceProperty.Name))
            {
                destElement.GetType().GetProperty(sourceProperty.Name).SetValue(destElement, sourceProperty.GetValue(sourceElement));
            }
        }
        destinationList.Add((ModelViewType)destElement);
    }

    return destinationList.Cast<object>().ToList();
}

我有一个包含对象列表的方法,我想在这个方法中调用扩展方法:

public void GridModel(IEnumerable<object> GridDataSource)        
{ 
   List<object> list = GridDataSource.ToModelViewObjectList<GridDataSource[0].GetType()>();
}

我应该写什么来代替 GridDataSource[0].GetType() ?

编辑:

我有一个带有对象参数的方法。我想创建对象类型的通用列表。

public void CreateListByNonGenericType(object myObject)
{
    Type objType = myObject.GetType();

    var lst = System.Collections.Generic.List < objType.MakeGenericType() > ();
}

我应该写什么来代替 objType.MakeGenericType()

最佳答案

What should I write instead of GridDataSource[0].GetType() ?

因为在编译时不知道类型,所以必须在运行时执行所有操作。所以你需要从方法定义中创建一个通用方法并调用它。类似以下内容:

GridModel(IEnumerable<object> GridDataSource)        
{ 
   Type dataSourceElementType = GridDataSource[0].GetType();

   //MyExtension is a type where ToModelViewObjectList defined
   MethodInfo methodDefinition = typeof(MyExtension).GetMethod("ToModelViewObjectList");

   //https://msdn.microsoft.com/en-us/library/system.reflection.methodinfo.makegenericmethod
   MethodInfo method = methodDefinition.MakeGenericMethod(dataSourceElementType)

   //https://msdn.microsoft.com/en-us/library/a89hcwhh
   List<object> list = (List<object>)method.Invoke(GridDataSource, null);
}

但您真正想要做的是接受 ToModelViewObjectList 的类型作为参数而不是泛型类型参数,如下所示,因为您不在函数外部使用 ModelViewType,因为您返回对象列表。此外,它将使您的代码清晰。

public static List<object> ToModelViewObjectList(this IEnumerable<object> source, Type modelViewType)
{
    List<object> destinationList = new List<object>();

    PropertyInfo[] ModelViewProperties = modelViewType.GetProperties();
    foreach (var sourceElement in source)
    {
        object destElement = Activator.CreateInstance(modelViewType);
        foreach (PropertyInfo sourceProperty in sourceElement.GetType().GetProperties())
        {

            if (ModelViewProperties.Select(m => m.Name).Contains(sourceProperty.Name))
            {
                destElement.GetType().GetProperty(sourceProperty.Name).SetValue(destElement, sourceProperty.GetValue(sourceElement));
            }
        }
        destinationList.Add(destElement);
    }

    return destinationList;
}

因此您几乎可以像预期的那样调用此扩展方法:

List<object> list = GridDataSource.ToModelViewObjectList(GridDataSource[0].GetType());

此外,最好使用其他方式获取 GridDataSource 的元素类型,而不是获取第一个元素的类型。

关于c# - 如何从对象类型定义泛型类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26687241/

相关文章:

c# - 单独项目中的 EF5 模型看不到 DbContext 方法

c# - C#中如何设置控件模板

java - 我怎样才能使这段代码与泛型一起使用?

c# - 静态类的扩展方法?

c# - 扩展枚举,矫枉过正?

c# - WPF:选择 Canvas 中的子控件

c# - 使用带有损坏引用的 .net DLL

java - 泛型和数组

c++ - 在 main() 中为通用模板类选择数据类型

C# 不明确的扩展方法