为属性分配值并重用代码

时间:2010-09-28 18:41:37

标签: c# asp.net c#-4.0

我有一些像这样的代码。但是想象一下,像这样的数百行都在多个函数中重复。

MyClass.prop1 = doingsomething("test1");
MyClass.prop2 = doingsomething("test55");

我想重用我的代码......我怎么能这样做?

我想做这样的事情:

    foreach(ClassInfo)
{
    dosomethingAssignment(ClassInfo.propertiesToAssign[i], ClassInfoStringIPassedToFunctionInFirstExample[i]);
}

也许这不是在C#中执行此操作的方法,但重用代码的最佳方法是什么?

4 个答案:

答案 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);
    }
}