私は次のプロパティを持つ3つのクラスがあります
Class A
{
public int CustID { get; set; }
public string Name{ get; set; }
}
Class B
{
public int CustID { get; set; }
public string Age { get; set; }
}
これらのクラスをすべて受け入れるジェネリックメソッドを1つ作成しました。
public void ProceesData<T>(IList<T> param1, string date1)
{
Parallel.ForEach(T, (currentItem) =>
{
// I want to aceess CustID property of param1 and pass that value to another function
GetDetails(CustID );
RaiseRequest<T>(param1);
});
}
CustIDプロパティは両方のクラス(つまり、クラスAとクラスB)に存在します。このジェネリックメソッドでCustIDプロパティにアクセスするにはどうすればよいですか?誰もがこれを助けることができますか
別の可能性は、System.Reflection
。
プロパティの名前を使用して、指定されたタイプPropertyInfo
からT
を取得します
そのPropertyInfo
を使用すると、GetValue
を使用して、そのプロパティの対応する値を取得できます。
これを例示するための小さなテストプログラムを次に示します。
public class ClassA
{
public int CustID { get; set; }
public string Name { get; set; }
}
public class ClassB
{
public int CustID { get; set; }
public string Age { get; set; }
}
public static void ProceesData<T>(IList<T> param1, string date1)
{
Parallel.ForEach(param1, (currentItem) =>
{
// I want to aceess CustID property of param1 and pass that value to another function
var value = typeof(T).GetProperty("CustID").GetValue(currentItem);
Console.WriteLine("Value: " + value);
});
}
public static void Main(string[] args)
{
List<ClassA> test = new List<ClassA>();
test.Add(new ClassA { CustID = 123 });
test.Add(new ClassA { CustID = 223 });
test.Add(new ClassA { CustID = 323 });
ProceesData<ClassA>(test, "test");
}
[〜#〜]編集[〜#〜]
これをもう少し普遍的にするには、パラメーター名をメソッドに渡すだけです。
public static void ProceesData<T>(IList<T> param1, string date1, string parameter)
{
Parallel.ForEach(param1, (currentItem) =>
{
// I want to aceess CustID property of param1 and pass that value to another function
var value = typeof(T).GetProperty(parameter).GetValue(currentItem);
Console.WriteLine("Value: " + value);
});
}
これで、使用するパラメーターを決定できます。
ProceesData<ClassA>(test, "test", "Name");
または
ProceesData<ClassB>(test, "test", "Age");
Gusmanによって提案されているように、ループの前に一度だけPropertyInfo
を取得することで、少し高速化できます。
PropertyInfo pi = typeof(T).GetProperty(parameter);
Parallel.ForEach(param1, (currentItem) =>
{
// I want to aceess CustID property of param1 and pass that value to another function
var value = pi.GetValue(currentItem);
Console.WriteLine("Value: " + value);
});
[〜#〜]編集[〜#〜]
どうやらパフォーマンスはあなたにとって問題のようです。これが比較です。少し時間があれば、自分で試すことができます。プロパティのアクセス時間を測定する場合:
public static void ProceesDataD<T>(IList<T> param1, string date1)
{
Parallel.ForEach(param1, (currentItem) =>
{
dynamic obj = currentItem;
int custId = obj.CustID;
});
}
public static void ProceesData<T>(IList<T> param1, string date1) where T : ICust
{
Parallel.ForEach(param1, (currentItem) =>
{
var value = currentItem.CustID;
});
}
public static void ProceesData<T>(IList<T> param1, string date1, string parameter)
{
PropertyInfo pi = typeof(T).GetProperty(parameter);
Parallel.ForEach(param1, (currentItem) =>
{
var value = pi.GetValue(currentItem);
});
}
public static void Main(string[] args)
{
List<ClassA> test = new List<ClassA>();
List<A> testA = new List<A>();
Stopwatch st = new Stopwatch();
for (int i = 0; i < 10000; i++)
{
test.Add(new ClassA { CustID = 123, Name = "Me" });
testA.Add(new A { CustID = 123, Name = "Me" });
}
st.Start();
ProceesData<ClassA>(test, "test", "CustID");
st.Stop();
Console.WriteLine("Reflection: " + st.ElapsedMilliseconds);
st.Restart();
ProceesData<A>(testA, "test");
st.Stop();
Console.WriteLine("Interface: " + st.ElapsedMilliseconds);
st.Restart();
ProceesDataD<ClassA>(test, "test");
st.Stop();
Console.WriteLine("Dynamic: " + st.ElapsedMilliseconds);
}
免責事項:コードパッセージを使用して、一度に1つだけ時間を測定します。プログラムをそのまま実行するのではなく、テストを1つずつ実行してください。
インターフェースの紹介:
interface ICust
{
public int CustID { get;}
}
class A : ICust
{
public int CustID { get; set; }
public string Name{ get; set; }
}
class B : ICust
{
public int CustID { get; set; }
public string Age { get; set; }
}
public void ProceesData<T>(IList<T> param1, string date1) where T : ICust
{
Parallel.ForEach(param1, (currentItem) =>
{
GetDetails(currentItem.CustID)
});
}
既存のクラスにインターフェースまたは基本クラスを導入できない場合、別のアプローチは動的を使用することです:
public void ProceesData<T>(IList<T> param1, string date1)
{
Parallel.ForEach(param1, (currentItem) =>
{
dynamic obj = currentItem;
int custId = obj.CustID ;
});
}
継承は機能します
public abstract class ABBase
{
public int CustID { gete; set; }
}
public class A : ABBase
{
public string Name { get; set; }
}
public class B : ABBase
{
public string Age { get; set; }
}
次に、ジェネリックメソッドの使用ではなく
public void ProcessData(IList<ABBase> param1, string date)
{
Parallel.ForEach(T, (currentItem) =>
{
GetDetails(CustID )
});
}
動的
この問題を解決する必要があります。キャストしたり、サークル内を移動したりしないでください。
List<T> products = new List<T>();
foreach (dynamic prod in products)
{
prod.ShopCategoryID = 1 ; // give you access to props
}