2016-06-17 4 views
0

У меня есть различные объекты, которые реализуют определенный интерфейс. В одном месте в моем коде я получаю весь экспорт интерфейсов и сохраняю фактическое имя класса в БД. Вот некоторые быстрый и грязный псевдо:Получение экспортированного интерфейса путем реализации имени класса

public interface ISomething { } 

[Export(typeof(ISomething))] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class Something : ISomething { } 

[Export(typeof(ISomething))] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class SomethingElse : ISomething { } 

public class Handler { 

    [Import] 
    CompositionContainer _container; 

    [ImportMany] 
    IEnumerable<ISomething> _somethings; 

    public void SaveSomething() { 
     foreach(ISomething something in _somethings) { 
      string className = something.GetType().Fullname; 
      SaveToDatabase(className); 
     } 
    } 
} 

Это работает просто отлично, и я могу легко получить все реализации ISomething. Однако мне также нужно получить новый экземпляр определенного имени класса в более поздней точке.

Если я попробую _container.GetExportedValues<ISomething> Я получаю как Something, так и SomethingElse. Если я попробую _container.GetExportedValue<ISomething>("SomethingElse"), я получаю ошибку композиции, говорящую, что он не может найти экспорт, соответствующий этому ограничению.

Итак, как я могу получить новый экземпляр SomethingElse, зная только название класса?

ответ

1

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

Что-то вроде этого:

public interface ISomething { } 

[Export(typeof(ISomething))] 
[Export("Something", typeof(ISomething))] 
public class Something : ISomething { } 

[Export(typeof(ISomething))] 
[Export("SomethingElse", typeof(ISomething))] 
public class SomethingElse : ISomething { } 

Теперь вы можете сделать это:

class Test 
{ 
    [ImportMany] 
    IEnumerable<ISomething> _somethings; 

    [Import("SomethingElse", typeof(ISomething))] 
    SomethingElse _somethingElse; 
} 
+0

А, вы можете поместить требуемое название контракта в атрибут '[Export]' ... Умный. Есть ли способ автоматически поместить полное имя класса в название контракта? Я могу сделать 'typeof (Something) .FullName' в коде, но не в атрибуте. – GTHvidsten

+0

@GTHvidsten, AFAIK, нет никакого способа сделать это. – dymanoid

0

Вы должны экспортировать SomethingElse Явные:

[Export(typeof(SomethingElse))] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class SomethingElse : ISomething { } 

Тогда _container.GetExportedValue<SomethingElse> работ. Также можно экспортировать один и тот же класс, указав имя для экспорта.

[Export("SomethingElse", typeof(ISomething))] 
+0

Да, но в то время код не знает о 'типа SomethingElse'. У меня есть строка, содержащая имя класса 'SomethingElse', а не самого класса ... и у меня никогда не будет этой ссылки. – GTHvidsten

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