2013-05-02 3 views
1

Итак, для двух разных пространств имен у меня есть запись класса. Я хотел бы вернуть соответствующий, основанный на типе, который передается. Чтобы попытаться сделать это, я попытался это сделать, но «T2» неверен. Как я могу это достичь?Один общий параметр типа, другой тип для возвращаемого типа?

public T2 GetGeneratedType<T1>(string name) where T1 : class where T2 : class 
{ 
    var type = typeof(T1); 
    var generatedName = type.AssemblyQualifiedName.Replace(type.Name, name); 
    return (T2)Activator.CreateInstance(Type.GetType(generatedName)); 
} 

Я не проверял это (не будет компилировать, очевидно), но как я могу сделать эту работу так, что если я прохожу Namespace1.SomeClass, я получить Namespace1.Record и в случае я прохожу в Namespace2.SomeOtherClass, я получаю Namespace2.Record (до тех пор, пока имя == «Запись»).

Первоначально я пытался Т для всего, и он не выдавал никаких сообщений об ошибках, но я хочу убедиться, что типы ввода и вывода могут быть разных типов.

Edit:

Я не may've объяснил полностью.

Я создаю аннотацию данных для раздвоенной записи (технически 3 человека должны иметь возможность назначать эту запись в любой момент времени из-за трех различных процессов, выполняемых на них. Они согласовываются после 3 процессы завершены). Поэтому namespace1 - это один проект (не в смысле Visual Studio), а namespace2 - другой. В namespace1 у вас есть ImportedRecord1 и в namespace2 ImportedRecord2 (оба отдельных проекта с отдельными свойствами, хотя более или менее служат той же цели). Namespace1 и Namespace2 имеют тип записи, относящийся к ImportedRecord для этого конкретного пространства имен, который затем будет преобразовывать в 3 "субректоры" другого типа (в основном импортированная запись этого проекта, но с полем, относящимся к одному из трех процессов).

+0

Итак, вы хотите, чтобы компилятор вычислил возвращаемый тип вашего метода на основе того, что метод делает во время выполнения? Боюсь, это просто невозможно. – svick

+0

Таким образом, не было бы способа передать в Namespace1.ImportedRecord1 как общий и строку «Запись» и было возвращено новое пространство имен Namespace1.Record? Это облом, но я ценю головы. – Robert

+0

Как тип времени компиляции? Нет. Как тип времени выполнения возвращаемого объекта? Да. – svick

ответ

2

Все, что вам нужно сделать, это установить тип возврата в динамический, а не в T2. Тип будет определен во время выполнения.

4

Вам просто нужно объявить второй тип как часть общей сигнатуры метода.

public T2 GetGeneratedType<T1, T2>(string name) where T1 : class where T2 : class 
{ 
    var type = typeof(T1); 
    var generatedName = type.AssemblyQualifiedName.Replace(type.Name, name); 
    return (T2)Activator.CreateInstance(Type.GetType(generatedName)); 
} 

EDIT:

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

  • Вы не будете развязка классов, как вы могли бы с заводом просто потому, что теперь вы возвращаете object типа которые вы будете вынуждены бросить на другую сторону.

  • Вы также теряете небольшую производительность при использовании отражения для создания этих объектов во время выполнения.

  • Просто одноразовая функция для этого конкретного сценария и подобной практики может привести к клонированию кода, если оно увековечено.

+0

Единственная проблема заключается в том, что я не уверен, что T2 будет до времени исполнения. Думаю, я нашел ответ на этот вопрос в этом вопросе http://stackoverflow.com/questions/11107170/property-type-as-generic-parameter?rq=1. По-видимому, это так же просто, как вернуть объект. – Robert

+0

@Robert. Какое значение передается в имени класса и имеет несколько строк кода, генерирует объект ... если вы остаетесь с жестким отбрасыванием его обратно в классе, вызванном вызовом этого метода? Вы просто застряли с запутанной связью, а не с прямой более плотной связью = D –

+0

@Robert Какова ваша основная цель при внедрении этого метода? –

1

Параметры общего типа могут работать только в «функции». Функция может иметь общее возвращаемое значение, но тип возвращаемого значения должен быть предоставлен вызывающим пользователем [это, конечно, возможно для функции, которая возвращает некоторый тип класса T, чтобы вернуть ссылку на экземпляр любого типа, полученного из T, но вызывающий объект все равно будет видеть тип возвращаемого значения как T.] Во многих случаях можно указать довольно неспецифический тип возвращаемого значения и заставить его вызвать его, если вызывающий абонент знает или может определить тип более точно, но этот подход имеет некоторые ограничения. Например, можно знать, что возвращаемый объект будет иметь тип, который удовлетворяет независимым ограничениям IFoo и IBar, но типы вещей, которые могут быть возвращены, могут не иметь общего типа супертипа, который также реализует IFoo и IBar. Нет никакого хорошего способа сохранения идентичности, чтобы передать такое возвращаемое значение методу, который требует чего-то, удовлетворяющего как ограничениям IFoo, так и IBar, так как нет ни одного типа, к которому могут быть применены все возможные значения.

Один из способов обойти это ограничение состоит в том, чтобы функция выставляла объект не путем возвращения его вызывающему, а путем передачи его в общий метод в предоставляемом вызывающим объектом объекте. Например, если один определяет интерфейсы:

interface IFooBarConsumer { PerformAction <T>(T thing) where T:IFoo,IBar; } 
interface IFooBarFeeder { FeedItem(IFooBarConsumer theConsumer); } 

Если класс, который реализует IFooBarFeeder имеет объект, который он знает, что удовлетворяет IFoo и IBar, он может передать этот объект в сдавший в IFooBarConsumer, и что потребитель будет в превратите его в методы, которые имеют как ограничения IFoo, так и IBar. Привлечение кода к потребителю, а не просто получение объекта от него, может быть неудобным, но это позволяет делать некоторые вещи безопасным по типу, которые в противном случае были бы невозможны.

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