簡體   English   中英

基於目標 class 類型的數據運行時分配

[英]Runtime assignment of data based on target class type

我有 5 個具有相同屬性但具有不同命名空間的不同類。

例如:

MyNameSpace1.Class1  - FirstName, LastName, Age
MyNameSpace2.Class2 -  FirstName, LastName, Age

等等

.

所有類都具有相同的屬性 - 例如,名字、姓氏、年齡等。

private void AssignData(int order, string firstName, string lastName)
{
  if(order==1)
 {
   var result=new MyNameSpace1.Class1();
   result.FirstName= firstName;
   result.LastName=lastName;
 }
 if(order==2)
 {
   var result=new MyNameSpace2.Class2();
   result.FirstName= firstName;
   result.LastName=lastName;
 }

}

上面,我只給出了兩個屬性,在我的真實示例中,有多個屬性被分配。

我試圖將其簡化為

private void AssignData(int order, string firstName, string lastName)
{
 if(order==1)
 {
   var result= GetInstance<MyNameSpace1.Class1>();
   result.FirstName=firstName;
   result.LastName=lastName;
 }
 if(order==2)
 {
   var result= GetInstance<MyNameSpace2.Class2>();
   result.FirstName=firstName; //repeated code , don’t want to use dynamic, 
                              //as I will not know the compile time issues.
   result.LastName=lastName;
 }

}

似乎,我再次重復相同的代碼,是否有一個選項,我需要直接分配 firstName、lastName 一次並創建 class 的運行時實例?

private T GetInstance<T>()
{
  return Activator.CreateInstance<T>();
}

我想要實現的是

private void AssignData(int order, string firstName, string lastName)
{
  var result; //this will not compile, object might, prefer not to use dynamic
  if(order==1)
  {
   result= GetInstance<MyNameSpace1.Class1>();
  }
  if(order==2)
  {
   result= GetInstance<MyNameSpace2.Class2>();
  }
  result.FirstName=firstName;//just do assignments 1 time
  result.LastName=lastName;
}

第一個也是最簡單的選擇就是使用dynamic類型:

class MyClass
{
    public int MyProperty { get; set; }
}

private dynamic GetInstance<T>()
{
    return Activator.CreateInstance<T>();
}

var instance = GetInstance<MyClass>();
instance.MyProperty = 5;
Console.WriteLine(instance.MyProperty);

所以我不推薦,因為它被認為不是很好。

第二個選項將使用這樣的反射:

var instance = GetInstance<MyClass>();
typeof(MyClass).GetProperty("MyProperty")
    .GetSetMethod()
    .Invoke(instance, new object[] { 5}); // sets MyProperty to 5

您可以“緩存” GetSetMethod的結果並重用它,因為反射也很慢。

最后一個選項是反射+表達式樹(您可以在其中生成“整體”方法來設置所有變量):

var type = typeof(MyClass);
var method = type.GetProperty(nameof(MyClass.MyProperty)).GetSetMethod();
var cls = Expression.Parameter(typeof(MyClass));
var val = Expression.Parameter(typeof(int));
var call = Expression.Call(cls, method, val);
// this action should be cached
var act = Expression.Lambda<Action<MyClass, int>>(call, cls, val).Compile();

var instance = GetInstance<MyClass>();
act(instance, 5); // sets MyProperty to 5

再次不要忘記緩存Expression.Lambda.Compile類型的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM