动态生成泛型类型的对象字段

时间:2015-02-26 17:49:37

标签: c# dynamic generic-programming

代码:

objectType request = factory.create<objectType>();

public class factory
{
    public static T create<T>() where T : new()
    {
      T obj = new T();
      PropertyInfo propertyInfo = obj.GetType().GetProperty("client_no");
      propertyInfo.SetValue(obj, CLIENT_NUMBER, null);
      return (T)Convert.ChangeType(obj, typeof(T));
     }
}

说明:

我正在创建一个设置2个对象属性的通用工厂fn()。

这些属性在我想要初始化的所有对象中都是一致的。

1)我如何调用我的函数

objectType request = factory.create<objectType>(); // <-- This works

1b)如果我愿意,可以从这里开始,我可以执行以下操作,但是在我的所有对象中都是重复的额外代码

request.client_no = CLIENT_NUMBER;

2)下面是我的工厂fn()

public static T create<T>() where T : new()
{
  T obj = new T();      

  // Here is where I am having trouble setting client_no I will explain in #3         

  return (T)Convert.ChangeType(obj, typeof(T)); // <-- This works returns generic type
}

3)我尝试过PropertyInfo来设置对象属性,如下所示

PropertyInfo propertyInfo = obj.GetType().GetProperty("client_no");
propertyInfo.SetValue(obj, CLIENT_NUMBER, null);

我也试过this

obj.GetType().GetProperty("client_no").SetValue(obj, CLIENT_NUMBER, null); 

我试过了

T obj = new T();      
var t = typeof(T);
var prop = t.GetProperty("client_no");
prop.SetValue(obj, CLIENT_NUMBER);

4)这是我收到的错误

  

对象引用未设置为对象的实例

更多/更新信息:

因此需要进一步研究。第三方对象属性没有getter和setter {get; set;}这就是为什么GetType()&amp; SetValue()不起作用。

我的同事指出该财产是一项单一的任务 这就是我们能做到的原因

request.client_no = CLIENT_NUMBER;

所以我的问题是如何设置这些属性?

3 个答案:

答案 0 :(得分:2)

使用反射,您可以执行以下操作:

public objectName updateAccountData(int accountId, Dictionary<string,string> accountData)
{
    var request = new objectName();
    var t = typeof(objectName);
    foreach (var k in accountData)
    {
        var prop = t.GetProperty(k.Key);   // you might want to check property exists before trying to set it
        prop.SetValue(request,k.Value);
    }
    return request;
}

这假定您的objectName类已经具有填充所需的所有属性。

请注意,反射比直接访问属性要慢,因此如果此代码位于应用程序的性能关键部分,则可能是一个问题(对其进行配置)。可以很容易地应用几个明显的优化。例如,您可以将PropertyInfo中检索到的所有GetProperty个对象存储在Dictionary<string,PropertyInfo>中,以避免不断查找它们。更复杂的是,您实际上可以使用表达式树来构建和编译表达式以进行属性访问。

对于t.GetField(k.Key)的{​​{1}}替换字段{/ 1}。

如果您不知道它是字段或属性(或两者兼而有之),那么您可以使用GetProperty然后检查GetMember来决定

答案 1 :(得分:1)

我看到了接受的答案,但是,这是另一种不涉及直接调用反射而是使用DLR的方法。

  public static T create<T>() where T : new()
  {
     T obj = new T();
     ((dynamic)obj).client_no = CLIENT_NUMBER;
     return obj;
  }

MSDN Dynamic Language Runtime Overview

这里必不可少的部分是,编译器不会自己编写反射调用,而是会处理它。上面的链接讨论了使用它直接进行反射调用的好处。

答案 2 :(得分:0)

解决。这是怎么回事。

我的主要问题是错误理解,我试图设置的项目不是属性,而是一个字段。

为了更好地了解差异,您可以查看this

以下是我修复它的方法:

我设置了通用

的字段类型
public static T create<T>() where T : new()
{
  T obj = new T();

  Type myType = typeof(T);
  FieldInfo myFieldInfo = myType.GetField("client_no");
  myFieldInfo.SetValue(obj, CLIENT_NUMBER);                        

  return obj;
}

特别感谢@MattBurland带领我朝着正确的方向前进。