Получить значение из универсального типа в C # - PullRequest
0 голосов
/ 25 июня 2018

Я хочу получить значение универсального типа, переданного методу, который выглядит следующим образом:

    public virtual Domains.Vegetable.Result Get<T>() where T: Domains.Vegetable.Entity
    {
        var type = typeof(T);
        var info = type.GetProperty("Segment");
        var value = info.GetValue(type).ToString(); // throws exception

        // NOTE: I have tried this, which works, but this feels wrong
        //var entity = Activator.CreateInstance<T>();
        //var segment = entity.Segment;

        // omitted for brevity
    }

Сущность с именем Domains.Vegetable.Entity выглядит примерно так:

public abstract class Entity
{
    /// <summary>
    /// 
    /// </summary>
    public virtual string Segment { get; set; }
}

, который затем реализуется для любого объекта по моему выбору:

public class Tomato: Vegetable.Entity
{
    /// <summary>
    /// 
    /// </summary>
    public override string Segment => "/patch/seeded";
}

Итак, если я вызову свой метод: Get<Tomato>(), я ожидаю получить значение "/ patch /"отобранный" назад в методе, упомянутом выше.

Это вообще возможно?

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Как все говорили вам, исключение связано с тем, что сегмент является свойством экземпляров томата, а не самого типа.И, как вы уже узнали, создание экземпляра позволяет получить к нему доступ без исключений.Есть 2 способа, которыми вы можете следовать, чтобы достичь ожидаемого результата, но невозможно определить, какой из них лучше, не зная контекста.Реальный вопрос здесь заключается в том, должно ли свойство быть статичным или нет.

Если он может быть статическим, просто удалите public virtual string Segment { get; set; } из Entity и измените public override string Segment => "/patch/seeded"; на public static string Segment => "/patch/seeded";.Таким образом, ваш код будет работать.

Недостатком является тот факт, что вы теряете ограничение каждого класса, производного от Entity, для реализации свойства Segment (кстати, я бы пометил его как абстрактный вместо виртуального),и это означает, что вы должны проверить на info != null, прежде чем использовать его в своем методе.

Если вы хотите / хотите сохранить ваш сегмент виртуальным / абстрактным, нет другого способа, кроме создания экземпляра T. Это можетсделать это с помощью отражения, как в вашем примере кода, но, возможно, было бы лучше добавить новое ограничение () для T следующим образом:

public virtual Domains.Vegetable.Result Get<T>() where T: Domains.Vegetable.Entity, new()
{
    var entity = new T();
    var segment = entity.Segment;

    // omitted for brevity
}
0 голосов
/ 25 июня 2018

Причина этого сбоя заключается в том, что info является PropertyInfo, представляющим свойство с именем Segment, принадлежащее типу Entity.(Предполагая, что Entity имеет такое свойство. Если это не так, info имеет значение null.)

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

var value = info.GetValue(instanceOfEntity).ToString();

Вместо этого вы пытаетесь прочитать свойство Segment из Entity из Type.

var value = info.GetValue(type).ToString();

Вы пытаетесь прочитать свойство одного класса (Segment) из экземпляра другого свойства (Type.) Даже если у Type было свойство с именем Segment itне будет работать, потому что info является свойством Entity и может быть прочитано только из экземпляра Entity.

В вашем методе нет экземпляра Entity.Возникает вопрос: с чего вы пытаетесь прочитать собственность?Если метод выглядел так:

public virtual Domains.Vegetable.Result Get<T>(T entity) where T: Domains.Vegetable.Entity
{
    var type = typeof(T);
    var info = type.GetProperty("Segment");
    var value = info.GetValue(entity).ToString(); // throws exception

    // other stuff
}

, тогда отражение могло бы работать, предполагая, что свойство существует.Но если бы собственность существовала, вы бы просто сделали это:

public virtual Domains.Vegetable.Result Get<T>(T entity) where T: Domains.Vegetable.Entity
{
    var value = entity.Segment.ToString(); // throws exception

    // other stuff
}

Но это не относится к делу.Вы получаете исключение, потому что вы пытаетесь прочитать свойство из одного класса в экземпляре другого класса.

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