Вызов нестатического члена статического свойства в статическом классе с отражением

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

public static class MyStaticClass
{
    private static MyAbstractType _MyAbstractImplementation;

    public static MyAbstractType MyAbstractImplementation
    {
        get => _MyAbstractImplementation ?? ( _MyAbstractImplementation = FindImplementation());
        private set => _MyAbstractImplementation = value;
    }
}

И я пытаюсь вызвать метод MyAbstractImplementation (который не содержит статических свойств или методов) через отражение:

var myAssembly = Assembly.Load("MyStaticClassAssembly")

var myType = myAssembly.GetTypes().First(t => t.Name == "MyAbstractType");

var myImplementation = myType.GetProperties()
    .First(p=>p.ReflectedType?.Name == "MyAbstractImplementation")
    .GetValue(null);

var obj = myType.GetMethod("SomeMethod")?.Invoke(
                null,
                new object[] 
                {
                    // Some args
                });

Приведенный выше код вызывает следующее исключение при получении значения MyAbstractImplementation:

System.Reflection.TargetException: Non-static method requires a target.

Очевидно, это потому, что я передаю null в GetValue(), поэтому я пытаюсь передать myAssembly, а не null, и получаю следующее исключение:

System.Reflection.TargetException: Object does not match target type.

В отчаянии я пытаюсь передать myType и myImplementation, но все равно получаю то же исключение.

Что я должен передать GetValue()?


person Minijack    schedule 04.02.2018    source источник
comment
Не могли бы вы также опубликовать код типа MyAbstractType   -  person Titian Cernicova-Dragomir    schedule 05.02.2018
comment
Вы извлекаете тип MyAbstractType не из MyStaticClass, поэтому я могу предположить, что MyStaticClass также имеет реализацию MyAbstractImplementation, но не является статической. Может быть, вы хотели сделать myAssembly.GetTypes().First(t => t.Name == "MyStaticClass");?   -  person Gusman    schedule 05.02.2018
comment
При исправлении опечатки в вопросе я обнаружил ошибку. MyAbstractType и MyAbstractImplementation имеют очень похожие имена в коде, и я их перепутал. Итак, я искал SomeMethod в MyAbstractType, а не MyAbstractImplementation.   -  person Minijack    schedule 05.02.2018


Ответы (1)


Из ошибки, которую вы получаете, MyAbstractImplementation не является статическим свойством, поэтому для его запуска требуется экземпляр. Вы в основном пытаетесь написать следующий код:

new MyAbstractType().MyAbstractImplementation.SomeMethod();

И для доступа к свойству, и для доступа к методу требуется цель для запуска (левая часть «.»). Итак, вам нужен экземпляр myType. Также методу потребуется экземпляр, являющийся результатом получения свойства (myImplementation).

var myAssembly = Assembly.Load("MyStaticClassAssembly");

var myType = myAssembly.GetTypes().First(t => t.Name == "MyAbstractType");
var myTypeInstance = Activator.CreateInstance(myType);  // Asuming has a default constructor 

var myImplementation = myType.GetProperties()
    .First(p => p.ReflectedType?.Name == "MyAbstractImplementation")
    .GetValue(myTypeInstance);

var obj = myType.GetMethod("SomeMethod")?.Invoke(
                myImplementation,
                new object[]
                {
                    // Some args
                });

Судя по тому, как вы пишете код, myImplementation также должен быть типа myType (myType.GetMethod("SomeMethod")), если он не заменяет его на: myImplementation.GetType().GetMethod("SomeMethod").

person Titian Cernicova-Dragomir    schedule 04.02.2018
comment
Спасибо за вашу помощь и ответ, просматривая свой вопрос после получения вашего ответа, я обнаружил ошибку. Я искал SomeMethod внутри типа, а не реализации. - person Minijack; 05.02.2018