установка свойства, передаваемого в качестве параметра, равным нулю - PullRequest
0 голосов
/ 28 января 2020

У меня есть следующий метод:

    public bool Method(object obj){
     var objType = obj.GetType();
     //do some reflection to get obj properties for some logic
     ...
     if(someCondition) {
      obj = null;
      return false;
     }

     if(condition2){ return true;}

     return false;
    }

Вызов метода:

var someObj = SomeObj();
Method(someObj.someProperty);

public class SomeObj : IEntity{
 public SomeProperty someProperty {get;set;} //this needs to be set to null in some conditions
}

Я хотел бы иметь общий метод, который принимает все типы объектов Entity, поэтому он типа "объект". Затем я хотел бы получить его тип и go через все свойства, чтобы выполнить некоторую логику c. В конце, основываясь на определенных условиях, я хотел бы установить переданный объект в null. Однако проблема в том, что переданный объект всегда является свойством какого-либо другого объекта Entity, поэтому я не могу установить для него значение ref. Как мне обойти это?

Ответы [ 2 ]

0 голосов
/ 28 января 2020

Передать выражение

В данный момент вы не передаете свойство в Method. Вы передаете значение объекта. Метод не знает, что такое исходное свойство, и поэтому не может установить его в null.

Чтобы обойти это, вы можете передать Expression, представляющее свойство вместо значения свойства. Затем ваш метод может проанализировать выражение и сделать все необходимое, включая чтение и установку значения.

Поэтому вместо этого

var someObj = new SomeObj();
Method(someObj.someProperty);  //Obtains the value of the property and passes it

Вызывающая сторона сделает это:

var someObj = new SomeObj();
Method(() => someObj.someProperty);  //Passes an expression representing the property

Чтобы изменить Method так, чтобы он мог работать таким образом, вам нужно немного разобрать выражения, но не намного:

static public bool Method<T>(Expression<Func<T>> expression) where T : class
{
    var memberExp = (MemberExpression)expression.Body;
    var propertyInfo = memberExp.Member as PropertyInfo;
    var targetObject = Expression.Lambda<Func<object>>(memberExp.Expression).Compile()();

    Console.WriteLine("Old value is {0}", propertyInfo.GetValue(targetObject));

    if (someCondition1)
    {
        propertyInfo.SetValue(targetObject, null); //Set it to null
        return false;
    }
}

Если вы планируете вызывать это часто и вы беспокоитесь о производительности Compile(), вы можете избежать компиляции с немного большим количеством кода:

static public bool Method<T>(Expression<Func<T>> expression)
{
    var memberExp = (MemberExpression)expression.Body;
    var propertyInfo = memberExp.Member as PropertyInfo;
    var propertyExpression = memberExp.Expression as MemberExpression;
    var targetObject = ((FieldInfo)propertyExpression.Member).GetValue((propertyExpression.Expression as ConstantExpression).Value);

    Console.WriteLine("Old value is {0}", propertyInfo.GetValue(targetObject));

    if (SomeCondition1)
    {
        propertyInfo.SetValue(targetObject, null);
        return false;
    }
}
0 голосов
/ 28 января 2020

Поскольку вы уже использовали рефлексию для определения информации о свойствах, производительность, скорее всего, не является вашей главной задачей. Вы можете передать объект и имя реквизита (поскольку вы уже использовали отражение, чтобы получить свойства obj) и установить для него значение null.

var a = new TestA();
a.Prop.Id = 1;

Method(a, "Prop");

Console.Write(a.Prop);

public bool Method(object obj, string propName)
{
    // if condition is met
    obj.GetType().GetProperty(propName).SetValue(obj, null);
    return false;
}

public class TestA
{
    public TestB Prop { get; set; } = new TestB();
}

public class TestB
{
    public int Id { get; set; }
}

В приведенном выше примере a.Prop будет иметь значение null.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...