2009-07-02 2 views
0

Предположим, у меня есть два класса, в которых есть статическая переменная XmlTag. Второй класс наследуется от первого класса. У меня есть метод шаблона, который должен получить XmlTag в зависимости от того, какой тип он использует. Какой был бы лучший способ выполнить это, не создавая экземпляр типа? Вот пример (который не будет компилироваться), который, надеюсь, иллюстрирует то, о чем я говорю.Метод шаблона доступа к статическим переменным issue

class A{ 
public static readonly string XmlTag = "AClass"; 
} 

class B : A { 
public static readonly string XmlTag = "BClass"; 
} 

Этот метод в настоящее время недействителен. Статические переменные не могут быть доступны из параметров типа.

string GetName<T>(T AClass) where T : A 
{ 
    return T.XmlTag; 
} 

ответ

5

Прежде всего, перестаньте думать об общих методах в качестве шаблонов. Они НЕ шаблоны. Они отличаются от шаблонов по-разному; ваше ожидание, что они ведут себя как шаблоны, возможно, то, что ведет вас в заблуждение в этой ситуации.

Вот серия статей, которые я написал о вашем сценарии и почему это незаконно.

http://blogs.msdn.com/ericlippert/archive/2007/06/14/calling-static-methods-on-type-variables-is-illegal-part-one.aspx

http://blogs.msdn.com/ericlippert/archive/2007/06/18/calling-static-methods-on-type-variables-is-illegal-part-two.aspx

http://blogs.msdn.com/ericlippert/archive/2007/06/21/calling-static-methods-on-type-variables-is-illegal-part-three.aspx

Обратите внимание, что, конечно, "динамический" особенность, которая мне намекают на в третьей части фактически является судоходство с C# 4.0.

Чтобы решить свой вопрос: «Каков наилучший способ сделать это?» Предположительно, у вас есть проблема, которая, по вашему мнению, позволит решить такой механизм. Этот механизм на самом деле не существует в C#. Невозможно определить, какую проблему вы пытаетесь решить, исходя из того, что вы хотите, чтобы этот механизм существовал. Вместо того, чтобы спрашивать: «Как я могу сделать эту невозможную вещь работать на C#?» вместо этого описать реальную проблему у вас есть, и мы можем взломать попытку придумать существующий механизм C#, который лучше решает вашу реальную проблему.

+0

Благодарим вас за ответ. Ваши статьи были интересными. Моя проблема довольно проста, но мне сложно подумать о хорошем решении: у меня есть несколько дочерних классов, каждая из которых имеет свою собственную уникальную константу xml-тега. У меня есть общий метод Load(), в другом классе, который принимает любой из этих дочерних классов и загружает экземпляры этого класса из XmlNode. Load() должен получить xml-тег в зависимости от типа, который он использует, чтобы он знал, какие теги xml искать. – Mav3rick

+0

Детские классы будут созданы только после того, как их xml-тег будет найден. – Mav3rick

+0

Сколько типов мы говорим здесь? Два? три? сотни? Или потенциально неограниченный номер? –

1

Нет прямого способа, которым вы могли бы это сделать, не прибегая к отражению.

Если вы действительно хотите сделать это (я призываю вас рассмотреть вопрос об изменении вашего высокого дизайна уровней первого):

Чтобы получить значение поля:

var returnValue = typeof(T).GetField("FieldName").GetValue(null); 

Чтобы получить свойство:

var returnValue = typeof(T).GetProperty("PropertyName").GetValue(null, null); 

Для вызова метода:

typeof(T).InvokeMember("MethodName", BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.NonPublic, null, null, null); 
0

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

class A{ 
public virtual string GetXmlTagName() 
    { 
    return "AClass"; 
    } 
} 

это решит ваш непосредственный симптом, но я не уверен в решении вашей проблемы. У этого есть запах унаследованного кода, но, не зная больше, я мог ошибаться, когда утверждаю, что понятие XML должно существовать в классе differrent и что в A и B нарушается принцип единой ответственности.В основном я знал бы из информации, которую я просто боюсь ее

+0

Да, это сработает, но мне нужно получить константу перед созданием класса. – Mav3rick

+0

Тогда опубликованный метод GetName не работал. Метод, который вы опубликовали, принимает аргумент T (где T: A), поэтому внутри этого метода вы всегда будете иметь объект (если вы не передадите значение null в качестве аргумента) –

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