【问题标题】:How to pass a dynamic model as 'T' to a C# generic function如何将动态模型作为“T”传递给 C# 泛型函数
【发布时间】:2020-02-21 11:15:49
【问题描述】:

我有一个通用函数,如下所示

private List<T> GetAll<T>()
{
    var listOfTModels = // gets the list of T from the database.

    return listOfTModels;
}

我需要根据将在运行时决定的字符串将模型 ( T ) 动态传递给此函数。

public void SomeFunction(string modelName)
{
     // Call the above Get method with modelName parameter as the 'T'

     var listOfModels = GetAll<something>(); //not sure what type this something should be "Type" or "string"

     // Further Logic on listOfModels
}

这是怎么做到的?

【问题讨论】:

  • 在 DbContext 上有一个方法 Set&lt;T&gt;(),它将返回一个 T 类型的 DbSet。您可以使用反射获得 T

标签: c# generics dynamic


【解决方案1】:

你需要使用反射来获得这样的方法:

typeof(ClassWithGetAll).GetMethod("GetAll",
                       BindingFlags.Instance | BindingFlags.NonPublic);

这将返回一个方法信息,然后您将使用它通过MakeGenericMethod 创建一个通用方法。

AFAIK 从字符串名称获取类型的唯一方法是使用Type.GetType,但您需要AssemblyQualifiedName,因此传入一个简短/简化的名称,如stringint 或类似名称这很可能会返回null

如果您知道如何获取限定名称或如何搜索类型,最后一件事就是调用从MakeGenericMethod 调用返回的MethodInfo,这是代码如何执行的示例看:

public void SomeFunction(string modelName)
{
    // No idea what the class/struct in which the method "GetAll" 
   // is called, hence use this name
    var instance = new ClassWithGetAll();

    //Retrieves the info of "GetAll<T>"
    MethodInfo method = typeof(ClassWithGetAll).GetMethod("GetAll", 
                        BindingFlags.Instance | BindingFlags.NonPublic);

    //Commented out as you will need to figure out how to get the 
    // assembly qualified name of the input model name, unless 
    // it is qualified.
    //modelName = GetAssemblyQualifiedName(modelName);

    Type modelType = Type.GetType(modelName);

    //Creates a generic method: "GetAll<T>" => "GetAll<modelType>"
    method = method.MakeGenericMethod(modelType);

    //Invokes the newly created generic method in the specified 
    // instance with null parameters, which returns List<modelType>
    object list = method.Invoke(instance, null);
}

【讨论】:

  • 谢谢文森特..会尝试这种方法,如果它对我的情况有帮助,请告诉您。
【解决方案2】:

我认为继承将是解决您的问题的正确方法。

public class TBase
{
    public int Prop { get; set; }
}
public class TChildOne : TBase
{

}
public class TChildTwo : TBase
{

}

public class GClass
{
    private List<T> GetAll<T>() where T : TBase
    {
        var listOfTModels = // gets the list of T from the database.
        return listOfTModels;
      }


    public void Main(string strType)
    {
        switch (strType)
        {
            case "TChildOne":
                {
                    var child = GetAll<TChildOne>();
                    break;
                }
            case "TChildTwo":
                {
                    var child = GetAll<TChildTwo>();
                    break;
                }
            default:
                throw new Exception("type not found");
        }

    }
}

【讨论】:

  • 谢谢。但就我而言,我将不得不为 4 种此类方法分别编写大约 70 个案例陈述,这是我试图避免的。
  • 如果数据库有200张表,如何实现继承? 600行代码的switch语句?这不是正确和动态传递对象(模型)名称
  • 答案基于问题,不包含使用它的上下文。如果您使用数据库,我建议您改用通用存储库。示例dotnettutorials.net/lesson/…
猜你喜欢
  • 2019-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-01
相关资源
最近更新 更多