c# - Как выполнить итерации через поля классов и установить свойства

Entity Framework не знает, как перевести ваш метод. Вы должны использовать метод, который возвращает Expression<Func<TsrEvent,EventModel>>, или свойство, которое его хранит.

public List<EventModel> GetEvents(bool showInactive, bool showPastEvents)
{
    return eventRepository
        .GetEvents(_customerId, showInactive, showPastEvents)
        .Select(ConvertPocoToModelExpr)
        .ToList();
}

private static Expression<Func<TsrEvent,EventModel>> ConvertPocoToModelExpr =>  (x)=>new EventModel()
    {
        Id = x.EventId,
        Name = x.EventName,
        Capacity = x.EventCapacity,
        Active = x.EventActive                
    };
50
задан vaxquis 30 August 2017 в 11:15
поделиться

7 ответов

public class Person
{
    public string Name { get; set; }
}

public class Employee
{
    public Person person = new Person();

    public void DynamicallySetPersonProperty()
    {
        var p = GetType().GetField("person").GetValue(this);
        p.GetType().GetProperty("Name").SetValue(p, "new name", null);
    }
}
28
ответ дан Konstantin Tarkus 7 November 2019 в 10:59
поделиться

Вот полный рабочий пример:

public class Person
{
    public string Name { get; set; }
}

class Program
{
    static void PropertySet(object p, string propName, object value)
    {
        Type t = p.GetType();
        PropertyInfo info = t.GetProperty(propName);
        if (info == null)
            return;
        if (!info.CanWrite)
            return;
        info.SetValue(p, value, null);
    }

    static void PropertySetLooping(object p, string propName, object value)
    {
        Type t = p.GetType();
        foreach (PropertyInfo info in t.GetProperties())
        {
            if (info.Name == propName && info.CanWrite)
            {
                info.SetValue(p, value, null);
            }
        }
    }

    static void Main(string[] args)
    {
        Person p = new Person();

        PropertySet(p, "Name", "Michael Ellis");
        Console.WriteLine(p.Name);
        PropertySetLooping(p, "Name", "Nigel Mellish");
        Console.WriteLine(p.Name);
    }
}

Править: добавленный вариант цикличного выполнения, таким образом, Вы видели, как циклично выполниться через объекты информации о свойстве.

32
ответ дан plinth 7 November 2019 в 10:59
поделиться

Со следующими Дополнительными методами, которые я создал, можно установить или получить любое значение свойства, даже если они вкладываются

GetPropertyValue (customObject, "Свойство. Вложенный. Ребенок. Имя");

или набор

SetPropertyValue (customObject, "Свойство. Вложенный. Ребенок. Имя", "мое пользовательское имя");

        private class TargetProperty
    {
        public object Target { get; set; }
        public PropertyInfo Property { get; set; }

        public bool IsValid { get { return Target != null && Property != null; } }
    }

    private static TargetProperty GetTargetProperty(object source, string propertyName)
    {
        if (!propertyName.Contains("."))
            return new TargetProperty { Target = source, Property = source.GetType().GetProperty(propertyName) };

        string[] propertyPath = propertyName.Split('.');

        var targetProperty = new TargetProperty();

        targetProperty.Target = source;
        targetProperty.Property = source.GetType().GetProperty(propertyPath[0]);

        for (int propertyIndex = 1; propertyIndex < propertyPath.Length; propertyIndex++)
        {
            propertyName = propertyPath[propertyIndex];
            if (!string.IsNullOrEmpty(propertyName))
            {
                targetProperty.Target = targetProperty.Property.GetValue(targetProperty.Target, null);
                targetProperty.Property = targetProperty.Target.GetType().GetProperty(propertyName);
            }
        }

        return targetProperty;
    }


    public static bool HasProperty(this object source, string propertyName)
    {
        return GetTargetProperty(source, propertyName).Property != null;
    }

    public static object GetPropertyValue(this object source, string propertyName)
    {
        var targetProperty = GetTargetProperty(source, propertyName);
        if (targetProperty.IsValid)
        {
            return targetProperty.Property.GetValue(targetProperty.Target, null);
        }
        return null;
    }

    public static void SetPropertyValue(this object source, string propertyName, object value)
    {
        var targetProperty = GetTargetProperty(source, propertyName);
        if(targetProperty.IsValid)
        {
            targetProperty.Property.SetValue(targetProperty.Target, value, null);
        }
    }

И вот несколько тестов для него

    [TestFixture]
public class ObjectExtensionsTest
{

    private class MockClass
    {
        public MockClass()
        {
            Nested = new NestedMockClass();
        }

        public string Id { get; set; }
        public string Name { get; set; }

        public string GetOnly { get { return "MockClass"; } }
        public string SetOnly { set { } }

        public NestedMockClass Nested { get; set; }
    }

    private class NestedMockClass
    {
        public string NestedId { get; set; }
        public string NestedName { get; set; }

        public string NestedGetOnly { get { return "NestedMockClass"; } }
        public string NestedSetOnly { set { } }
    }

    [Test]
    public void TestShouldFindProperty()
    {
        MockClass mockObject = new MockClass();

        Assert.IsTrue(mockObject.HasProperty("Id"));
        Assert.IsTrue(mockObject.HasProperty("Name"));
        Assert.IsTrue(mockObject.HasProperty("GetOnly"));
        Assert.IsTrue(mockObject.HasProperty("SetOnly"));
        Assert.IsTrue(mockObject.HasProperty("Nested"));
        Assert.IsTrue(mockObject.HasProperty("Nested.NestedId"));
        Assert.IsTrue(mockObject.HasProperty("Nested.NestedName"));
        Assert.IsTrue(mockObject.HasProperty("Nested.NestedGetOnly"));
        Assert.IsTrue(mockObject.HasProperty("Nested.NestedSetOnly"));
    }

    [Test]
    public void TestShouldGetPropertyValue()
    {
        MockClass mockObject = new MockClass();

        mockObject.Id = "1";
        mockObject.Name = "Name";
        mockObject.Nested.NestedId = "NestedId";
        mockObject.Nested.NestedName = "NestedName";

        Assert.AreEqual(mockObject.Id, mockObject.GetPropertyValue("Id"));
        Assert.AreEqual(mockObject.Name, mockObject.GetPropertyValue("Name"));
        Assert.AreEqual(mockObject.GetOnly, mockObject.GetPropertyValue("GetOnly"));
        Assert.AreEqual(mockObject.Nested.NestedId, mockObject.GetPropertyValue("Nested.NestedId"));
        Assert.AreEqual(mockObject.Nested.NestedName, mockObject.GetPropertyValue("Nested.NestedName"));

    }

    [Test]
    public void TestShouldSetPropertyValue()
    {
        MockClass mockObject = new MockClass();

        mockObject.SetPropertyValue("Id", "1");
        mockObject.SetPropertyValue("Name", "Name");
        mockObject.SetPropertyValue("Nested.NestedId", "NestedId");
        mockObject.SetPropertyValue("Nested.NestedName", "NestedName");

        Assert.AreEqual(mockObject.Id, "1");
        Assert.AreEqual(mockObject.Name, "Name");
        Assert.AreEqual(mockObject.Nested.NestedId, "NestedId");
        Assert.AreEqual(mockObject.Nested.NestedName, "NestedName");

    }
}

Надеюсь, что Вы находите это полезным.

10
ответ дан Community 7 November 2019 в 10:59
поделиться

Вы пытаетесь установить свойство Name _person поля класса своего Сотрудника. Это не имеет того. Попробуйте это:

prop.SetValue(((FieldInfo)member).GetValue(this), "new name", null)

Не уверенный, если необходимо бросить первый аргумент как это:

prop.SetValue((Person)((FieldInfo)member).GetValue(this), "new name", null)

Это затем применяет его к значению _person поля вместо этого.

5
ответ дан David M 7 November 2019 в 10:59
поделиться

Вы попытка работать SetValue() на свойстве Name из переменной member это - объект MemberInfo, и этот proeprty только для чтения.

Обратите внимание, что Вы не должны выполнять итерации по всему memebers, и Вы не должны получать поле _person с отражением, поскольку это определяется в том же классе как метод DynamicallySetPersonProperty().

Так код shoul чтение как это.

PropertyInfo property = this._person.GetType().GetProperty("Name");

property.SetValue(this._person, "new name", null);

Первая строка перестанет работать если _person является пустым. Таким образом, можно использовать reflectiopn для получения типа поля.

FieldInfo field = this.GetType().GetField("_person", BindingFlags.Public);

PropertyInfo property = field.FieldType.GetProperty("Name");

Но теперь доступ к этому свойству все еще перестанет работать если _personявляется пустым.

property.Setvalue(field.GetValue(this), "new name", null);
4
ответ дан Daniel Brückner 7 November 2019 в 10:59
поделиться

Взгляните на эту статью CodeProject, связанную с тем, что Вы пытаетесь сделать

http://www.codeproject.com/KB/cs/fast_dynamic_properties.aspx

0
ответ дан Chris Ballance 7 November 2019 в 10:59
поделиться

попробуйте следующее:

public static void ApplyPropertyChanges(this object objDest, object objToCopyFrom)
    {
        if (objDest == null)
            throw new ArgumentNullException();
        if (objToCopyFrom == null)
            throw new ArgumentNullException("objToCopyFrom");
        if (objDest.GetType() != objToCopyFrom.GetType())
            throw new Exception("Invalid type. Required: \"" + objDest.GetType().ToString() + "\"");

        foreach (System.Reflection.PropertyInfo piOrig in objDest.GetType().GetProperties())
        {
            object editedVal = objToCopyFrom.GetType().GetProperty(piOrig.Name).GetValue(objToCopyFrom, null);

            piOrig.SetValue(objDest,
            editedVal,
            null);
        }
    }

пример использования:

    public ActionResult Edit(Team editedTeamData)
    {
        if (!ModelState.IsValid)
            return View();

        Team origTeam = (from t in _db.Teams
                         where t.TeamID == editedTeamData.TeamID
                         select t).FirstOrDefault();

        origTeam.ApplyPropertyChanges(editedTeamData);
        _db.SubmitChanges();

        return RedirectToAction("Index");

    }
1
ответ дан 7 November 2019 в 10:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: