2016-07-05 2 views
1

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

Interface ISchema {} 

class Schema:ISchema{} 

class TableSchema:Schema{} 

class ViewSchema:Schema{} 

У меня есть другой DLL, имеющий следующую иерархию:

Interface ISearch {} 

class Table:ISearch{} 

class View:ISearch{} 

Следующий код запускает операцию поиска по Таблице или Просмотр в соответствии с выбором пользователя:

private void FindNowButton_Click(object sender, EventArgs e) 
{ 
    // return Table or View according to user selection. (Property is an internal class helping to retrieve the selected type) 
    var type = (ObjectsTypeComboBox.SelectedItem as Property).Type; 

    // Create an instance of table or View as ISearch 
    var instance = (ISearch)Activator.CreateInstance(type); 

    // Call to relevant Search (table.Search or View.Search) 
    // _dataManager help to get the records from Schema hierarchy 
    // text is the text to search 
    var result = instance.Search(_dataManager, FindWhatTextBox.Text); 

    // Show in DataGridView the result 
    FindResultsDGV.DataSource = result; 
} 

Каждый метод поиска возвращает список. Мне нужно отображать разные столбцы в сетке. TableSchema и ViewSchema имеют разные свойства, а выполнение выполняется следующим образом.

FindResultsDGV.DataSource = result.Cast<TableSchema> ; // or result.Cast<ViewSchema> 

Как я могу динамически получить правильный тип на этом этапе?

Любое другое решение приветствуется

UPDATE:

Согласно @GiladGreen

public interface ISearchSchemaFactory 
{ 
    ISearch<ISchema> GetSearch(Type schemaType); 
} 

public class Factory : ISearchSchemaFactory 
{ 
    public ISearch<ISchema> GetSearch(Type schemaType) 
    { 
     if (schemaType.Equals(typeof(Table))) 
     { 
      return new BL.AdvancedSearch.Table(); // Getting an error here 
      // Cannot implicitly convert type 'Table' to 'ISearch<ISchema>'. An explicit conversion exists (are you missing a cast?) 
     } 
     else if (schemaType.Equals(typeof(View))) 
     { 
      // TODO 
     } 

     return null; // TODO 
    } 
} 
+0

Считаете ли вы использование Generics? – Aron

ответ

1

Я предлагаю вам изменить ISearch следующим образом:

Interface ISearch<out TSchema> where TSchema: ISchema 
{ 
    TSchema Search(....); 
} 

class Table : ISearch<TableSchema> 
{ 
    public TableSchema Search(....) 
    { 
     //Some searching code 
    } 
} 

class View:ISearch<ViewSchema> 
{ 
    public ViewSchema Search(....) 
    { 
     //Some searching code 
    } 
} 

Тогда вы также можете сделать ISearchSchemaFactory, который даст вам экземпляр правильного ISearch, что вам нужно в соответствии с TSchema вы даете ему:

public interface ISearchSchemaFactory 
{ 
    ISearch<ISchema> GetSearch(Type schemaType); 
} 

И использование: var search = factory.GetSearch(type);


Factoy Пример реализации

public class MappingSearchSchemaFactory : ISearchSchemaFactory 
{ 
    public MappingSearchSchemaFactory(Dictionary<Type, ISearch<ISchema>> mapping) 
    { 
     Mapping = mapping; 
    } 

    ISearch<ISchema> GetSearch(Type schemaType) 
    { 
     ISearch<ISchema> result; 
     if(!Mapping.TryGetValue(schemaType, out result) 
     { 
      //Some logging or throwing exception behavior - depends what you want 
     } 
     return result; 
    } 
    public Dictionary<Type, ISearch<ISchema>> Mapping { get; set; } 
} 

Эта конкретная реализация получает «некоторые одно "отображение. Возможный код инициализации:

Но я бы не рекомендовал этого. Я бы посмотрел на Dependency Injection и IoC Containers для управления инициализацией моих объектов. Я лично использую Castle Windsor

+1

вам нужно будет вызвать метод 'GetSearch', как этот' GetSearch () 'или' GetSearch () ', поэтому проблема остается. –

+0

Правда. Отредактирован метод фабрики. –

+0

теперь ваш метод не является общим, поэтому 'ISearch GetSearch (Type schemaType);' не будет компилироваться. –

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