我有一些像这样的代码。但是想象一下,像这样的数百行都在多个函数中重复。
MyClass.prop1 = doingsomething("test1");
MyClass.prop2 = doingsomething("test55");
我想重用我的代码......我怎么能这样做?
我想做这样的事情:
foreach(ClassInfo)
{
dosomethingAssignment(ClassInfo.propertiesToAssign[i], ClassInfoStringIPassedToFunctionInFirstExample[i]);
}
也许这不是在C#中执行此操作的方法,但重用代码的最佳方法是什么?
答案 0 :(得分:1)
假设你有一个班级
public class MyClassAssigments
{
public string PropertiesToAssign { get; set; }
public string ClassInfoStringIPassedToFunctionInFirstExample{ get; set; }
}
并说出一个包含这些数据的List
List<MyClassAssigments> MyData
然后你可以有类似的东西:
PropertyInfo[] pInfos = typeof(MyClassType).GetProperties(); //Assuming MyClass is of Type MyClassType
Foreach (MyClassAssigments aData In MyData)
{
PropertyInfo eachPInfo in pInfos.Where(W => W.Name == aData.PropertiesToAssign)).SingleOrDefault();
If (eachPInfo != null)
{
eachPInfo.SetValue(MyClass, doingsomething(aData.ClassInfoStringIPassedToFunctionInFirstExample), null);
}
}
答案 1 :(得分:1)
在给定PropertyInfos数组或属性字符串名称的情况下,您可以创建一个反射性地实例化该属性的方法:
var properties = MyClass.GetType().GetProperties();
var values = new [] {"test1", "test55", ... };
for(var i=0; i<properties.Count; i++)
DoSomethingAndAssign(properties[i], values[i], MyClass);
public void DoSomethingAndAssign(PropertyInfo prop, string theValue, Object theClass)
{
var setValue = /*do anything you want based on theValue before setting*/
//will throw an exception if theClass is null, theClass doesn't have the property,
//or the property cannot be set to a value of setValue's type.
prop.SetValue(theClass, setValue, null);
}
请注意,这将比静态分配值慢得多,因为反射算法通常都是如此。无论MyClass的结构如何,它都会编译,所以你必须在运行时对它进行广泛的测试。
如果您的类包含许多非常相似的属性,另一种可能的方法是定义索引器。索引器使类看起来像索引集合,如数组或List。但是,它可能涉及反射算法或switch语句以将值转换为a。一个更容易和更优雅的方法是让MyClass包含你要迭代的属性的Dictionary,并将属性访问器和索引器绑定到字典。
所有这些基本上都隐藏了属性分配列表,或者实现了一种循环分配的效率较低的方式。如果你有数百个属性,这将节省你一些打字,但我会考虑重构该类来减少或收集它的属性。如果您在系统中的许多位置设置了五个属性,我会看到一个知道如何初始化类的类是否可行。
答案 2 :(得分:1)
这是明确的代码:
Baseball.Mass = 20;
Baseball.InitialVelocity = new velocity(100, 0, 0);
Baseball.Spin = new Spin(0,0,1, 20);
这不是明确的代码:
AssignProperties(PropertiesBag, Baseball.PropertiesBag);
在你走这条路之前问问自己,为什么我要重用这段代码?有时它没问题,就像你初始化一个对象一样(这就是序列化和生成器)课程是为了)。很多时候它都不行,就像你在事务处理过程中更改对象一样。保持差异清晰和清晰是很重要的。
答案 3 :(得分:0)
这是一个简单的例子。 请注意,如果要在不同的地方重复使用此方法,则应使用属性更好地指定映射 除非您确定需要,否则不要这样做。反射驱动的代码很不错但如果你不确定你在做什么,它可能是一个调试和维护的怪物。
class Guy {
private static readonly Dictionary<string, string> mappings = new Dictionary<string, string> {
{ "Name", "nameProp" },
{ "Age", "ageProp" }
};
public string Name { get; set; }
public int Age { get; set; }
public void RetrieveProperties (Func<string, object> valueRetriever)
{
foreach (var prop in GetType ().GetProperties (BindingFlags.Instance | BindingFlags.Public)) {
var mapping = mappings [prop.Name];
var value = valueRetriever (mapping);
prop.SetValue (this, value, null);
}
}
public override string ToString ()
{
return string.Format ("I'm {0}, {1} years old.", Name, Age);
}
}
public static class Program
{
static object GetItemPropertyValue (string itemName)
{
if (itemName == "nameProp")
return "John";
if (itemName == "ageProp")
return 42;
throw new NotImplementedException ();
}
public static void Main ()
{
var john = new Guy ();
john.RetrieveProperties (GetItemPropertyValue);
Console.WriteLine (john);
}
}