2012-06-20 6 views
2

Как я могу назвать частный метод базой одного класса?Отразить частный метод реализации из абстрактного класса?

Вот простой пример моей структуры (этот код включен со ссылкой):

public abstract class Something { 
} 
internal class ImplBase : Something { 
    private void CallMe(string s) {} 
} 
internal class RealImpl : ImplBase { 
} 

До сих пор у меня есть instanence из RealImpl, которая видна как Something. Как получить доступ к методу CallMe?

Я пытаюсь этот код здесь:

Type type = obj.GetType(); // returns RealImpl 
bool supported = false; 
// a loop to be a little more flexible 
for(Type t = type; t.Name != "Object"; t = t.BaseType) { 
    if(t.Name == "ImplBase") { 
     supported = true; 
     type = t; 
     break; 
    } 
} 
if(supported) { 
    var callme = type.GetMethod("CallMe", BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(string) }, new ParameterModifier[] {}); 
    callme.Invoke(obj, new object[] { "hi" }); 
} else { 
    throw new NotSupportedException("The type " + type.Name + " is not supported."); 
} 

Если я закомментировать type = t; я получу за callme значение null. Если я использую код, как здесь, я получаю исключение, кричащее о внутреннем NullReferenceException.


С моим хака я произвел NullReferenceException внутри Lib до сих пор моя вина. Приведенный выше код теперь исправлен (при упрощении было 3 ошибки).

ответ

2

Ваш метод назван callMe, не CallMe, поэтому изменить его нравится:

var callme = type.GetMethod("callMe"... 

также вызвать его на obj (не уверен, что self есть):

callme.Invoke(obj, new object[] { "hi" }); 

кроме того, вы не» t нужен весь этот код для определения, является ли objImplBase или нет:

if(obj is ImplBase) 
{ 
    var callme = type.GetMethod("callMe", BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(string) }, new ParameterModifier[] {}); 
    callme.Invoke(obj, new object[] { "hi" }); 
} 
+0

Вы указали мне на две небольшие ошибки в моем примере кода. Это не моя ошибка. Но спасибо вам все равно +1 :) О вашем редактировании: мне очень нравится этот оператор 'is', но класс' ImplBase' является внутренним внешним lib. Так что это не сработает. – rekire

+0

@rekire Ваш примерный код отлично работает с изменениями, которые я рекомендовал. Что такое ошибка? –

+0

Эти проблемы, о которых вы указали, являются просто глупыми ошибками, делая эту проблему более общей. Мой настоящий код (только с другими именами, такими как * self *), код работает.За исключением того, что я получаю 'TargetInvocationException' с внутренним' NullReferenceException'. – rekire

2

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

public abstract class Something { 
} 
internal class ImplBase : Something { 
    protected void callMe(string s) {} 
} 
internal class RealImpl : ImplBase { 
} 

или

public abstract class Something { 
} 
internal class ImplBase : Something { 
    private void callMe(string s) {} 
    public void CallMe(string s) { this.callMe(s);} 
} 
internal class RealImpl : ImplBase { 
} 

Насколько я знаю, отражение будет работать только на открытых членов/методов/и т.д.. так или иначе.

+0

Невозможно, чтобы все классы были определены во внешней библиотеке. Который я не могу редактировать, просто задумайтесь. – rekire

+0

О вашем редактировании: неверно, можно ли отображать частных членов с флагом 'BindingFlags.NonPublic'. Я имею в виду, что могу «видеть» этот метод, которого я просто не могу назвать ;-) – rekire

+0

Я не знал этого, спасибо за разъяснение. Тем не менее, доступ к/вызову частных членов приведет к поражению цели частного модификатора. – Manuzor

Смежные вопросы