【问题标题】:Create instance of a parameterized generic object with all parameters set to null创建参数化通用对象的实例,所有参数都设置为 null
【发布时间】:2015-07-10 19:09:12
【问题描述】:

假设具有参数化构造函数的类为:

MyObject(string param1, string param2, string param2)
{
   ...
}

我有一个 Generic 方法,它返回一个 Generic Class 的实例和 MyObject 就是这样的例子之一。

如何使用参数化构造函数实例化泛型类 并将空值传递给它的所有参数?这是需要的 泛型类的属性稍后会被填充 阶段。

我尝试过使用Activator 作为:

public static T GetGenericObject<T>()
{
   T resource = (T)Activator.CreateInstance(typeof(T), null); 
   ... 
}

但是我得到一个异常,我在MyObject 中没有无参数构造函数。我知道我可以轻松添加一个,但不能修改类(不要问为什么)。

【问题讨论】:

  • 我相信你知道这一点,但必须说:在构造函数中要求属性,然后传入空值,因为它们可以稍后填充,这似乎是一个非常糟糕的主意。

标签: c# generics constructor instantiation activator


【解决方案1】:

您可以通过反射检测有多少个参数,然后在Activator.CreateInstance() 中为每个参数传入空值:

var parameters = typeof(T)
    .GetConstructors()
    .Single()
    .GetParameters()
    .Select(p => (object)null)
    .ToArray();
T resource = (T)Activator.CreateInstance(typeof(T), parameters); 

请注意,这是假设只有一个构造函数,并且它只适用于引用类型,所以它相当脆弱。

【讨论】:

  • 好方法!但是我在 .Select(p => null) 行上得到“无法从使用中推断出来..”
【解决方案2】:

使用带参数的重载并创建一个对象数组来传递,其中 null 表示每个需要的参数。

根据您的评论,您当然可以告诉该方法基于固定数量的元素创建一个已初始化但为空的对象数组。然而,正如在其他 cmets 中提到的,这是非常危险的,并且会让您头疼。

var instance = GetGenericObject<MyObject>(3);

public static T GetGenericObject<T>(int numberOfNullParametersToPass)
{
    var nullParams = new object[numberOfNullParametersToPass];
    T resource = (T)Activator.CreateInstance(typeof(T), nullParams); 
    return resource;
}

就目前的代码而言,您明确告诉Activator.CreateInstance 选择无参数构造函数。通过指定所有三个参数(即使它们为空),您选择了正确的构造函数。

在调用链的某个时刻,您需要告诉Activator.CreateInstance 选择哪个构造函数。另一种方法是选择第一个可能的构造函数。

public static T GetGenericObject<T>()
{
    var paramLength = typeof(T).GetConstructors().FirstOrDefault().GetParameters().Length;
    var parameters = new object[paramLength]; 
    T resource = (T)Activator.CreateInstance(typeof(T), parameters); 
    return resource;
}

【讨论】:

  • @eYe:您确定所有参数都将始终是引用类型吗?他们中的任何一个都可以是int,例如?
  • 我应该提到,我的错误,参数只能是字符串或日期时间,所以是的,都是引用类型。
  • @eYe:DateTime 不是引用类型——它是值类型,所以你不能将null 传递给它。您想为 DateTime 参数传递什么值?
【解决方案3】:

下面是简单的方法,不用担心参数,避免不存在默认构造器的错误

var ctors = typeof(T).GetConstructors();
var ctor = ctors[0];
var instance = ctor.Invoke(new object[ctor.GetParameters().Length]);

【讨论】:

  • 也试过了 -> NullRef 异常
猜你喜欢
  • 2017-07-31
  • 2011-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多