Присвоение значений свойствам и повторное использование кода - PullRequest
1 голос
/ 28 сентября 2010

У меня есть такой код.Но представьте себе, что сотни подобных строк дублируются в нескольких функциях.

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

Я хочу повторно использовать свой код ... как я могу это сделать?

Я хочу сделатьчто-то вроде этого:

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

Может быть, это не способ сделать это в C #, но как лучше всего использовать мой код?

Ответы [ 4 ]

1 голос
/ 28 сентября 2010

Вы можете создать метод, который будет рефлексивно создавать экземпляр свойства, учитывая массив имен 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, поэтому вам придется тщательно тестировать его во время выполнения.

Другой возможный метод, если ваш класс содержит много очень похожих свойств, - определить индексатор. Индексатор делает класс похожим на индексированную коллекцию, как массив или список. Впрочем, для преобразования значения в a, скорее всего, потребуется рефлексивный алгоритм или оператор switch. Гораздо более простой и изящный способ состоит в том, чтобы MyClass содержал словарь свойств, через которые вы хотите выполнить итерацию, и привязывал средства доступа к свойствам и индексатор к словарю.

Все это в основном либо скрывает список назначений свойств, либо реализует менее эффективный способ циклического выполнения назначений. Если у вас есть сотни свойств, это избавит вас от необходимости печатать, но я бы посмотрел на рефакторинг этого класса для уменьшения или сбора его свойств. Если у вас есть пять свойств, которые установлены во многих местах системы, я бы посмотрел, возможен ли класс, который знает, как инициализировать ваш класс.

1 голос
/ 28 сентября 2010

Это понятный код:

Baseball.Mass = 20;
Baseball.InitialVelocity = new velocity(100, 0, 0);
Baseball.Spin = new Spin(0,0,1, 20);

Это не понятный код:

AssignProperties(PropertiesBag, Baseball.PropertiesBag);

Спросите себя, прежде чем идти по этому пути слишком далеко, почему я хочу повторно использовать этот код? Иногда это нормально, например, когда вы инициализируете объект (что такое классы сериализации и генератора) для). В большинстве случаев это не так, как при изменении объекта во время обработки транзакции. Важно сохранить разницу в чистоте.

1 голос
/ 28 сентября 2010

Скажем, у вас есть класс

public class MyClassAssigments
{
    public string PropertiesToAssign { get; set; }
    public string ClassInfoStringIPassedToFunctionInFirstExample{ get; set; }
}

И произнесите список, содержащий эти данные

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);
   }
}
0 голосов
/ 28 сентября 2010

Это простой пример, который делает это.Обратите внимание, что вам лучше указывать сопоставления с использованием атрибутов, если вы собираетесь использовать этот подход в разных местах.
Также не делайте этого, если вы не уверены, что это требуется .Управляемый отражениями код хорош, но он может быть монстром для отладки и поддержки, если вы не уверены, что делаете.

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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...