2013-08-02 2 views
2

Как создать общий метод с необязательным общим типом? Это то, что я прямо сейчас, который работаетОбщий метод с дополнительным общим параметром

public GridViewColumn<T> Column<D>(String HeaderText, D decorator) where D: IColumnDecorator, new() 
     { 
      GridViewColumn<T> column = new GridViewColumn<T>(); 
      column.HeaderText = HeaderText; 
      column.Decorator = new D(); 
      return column; 
     } 

Как вы можете видеть, я должен создать экземпляр типа D (реализует IColumnDecorator) внутри метода Column().

Вопрос заключается в том, что тип «D» не является обязательным. Если Null, я хочу явно использовать стандартный ColumnDecorator, который у меня есть. что-то вроде

public GridViewColumn<T> Column<D>(String HeaderText, D decorator) where D: IColumnDecorator, new() 
     { 
      GridViewColumn<T> column = new GridViewColumn<T>(); 
      column.HeaderText = HeaderText; 
      if(decorator ==null) 
      { 
       column.Decorator = new DefaultColumnDecorator(); 
      } 
      else{ 
       column.Decorator = new D(); 
      } 
      return column; 
     } 

Пожалуйста, помогите. Благодаря!

[Изменить].

Вот как я хочу использовать его в бритвенном MVC, если у меня есть реализация на заказ IColumnDecorator

@Model.[IEnumerable].Grid(grid=>{ 
     .. 
     ... 
     grid.columns(
     grid.Column<MyOwnColumnDecorator>("FirstColumn") 
    ) 
}); 

Если у меня нет какого-либо и хочу использовать по умолчанию, то я хочу, чтобы быть в состоянии сделать что-то вроде

@Model.[IEnumerable].Grid(grid=>{ 
      .. 
      ... 
      grid.columns(
      grid.Column("FirstColumn",null) or simply grid.Column("FirstColumn"); 
     ) 
    }); 
+6

Почему ваш первый метод имеет проход вызывающего абонента в экземпляре 'D' вообще? Вы никогда не используете его. –

+0

Зачем вам нужно создать экземпляр типа 'D' внутри' Column() '? Было бы гораздо более гибким, если бы вызывающий вызывал в этом экземпляре. –

+0

Джастин, что ты имеешь в виду? и Yuxiu, я сделал это, потому что я не хочу, чтобы мой звонящий должен был указать «новое» ключевое слово конкретного типа, когда они звонят. – Liming

ответ

6

в текущем коде, вам не нужно параметр decorator, так как вы создаете новый экземпляр D и используете его вместо этого.

public GridViewColumn<T> Column<D>(String HeaderText) where D: IColumnDecorator, new() 
{ 
    GridViewColumn<T> column = new GridViewColumn<T>(); 
    column.HeaderText = HeaderText; 
    column.Decorator = new D(); 
    return column; 
} 

Если у вас есть тип параметр, используемый по умолчанию, вам не нужно использовать дженерики:

public GridViewColumn<DefaultColumnDecorator> Column(String headerText) 
{ 
    return Column<DefaultColumnDecorator>(headerText); 
} 

В качестве альтернативы вы можете сохранить параметры и удалить new() ограничение:

public GridViewColumn<T> Column<D>(String HeaderText, D decorator) where D : IColumnDecorator 
{ 
    GridViewColumn<T> column = new GridViewColumn<T>(); 
    column.HeaderText = HeaderText; 
    column.Decorator = decorator; 
    return column; 
} 

public GridViewColumn<DefaultColumnDecorator> Column(String headerText) 
{ 
    return Column(headerText, new DefaultColumnDecorator()); 
} 
+0

новый D() был бы лучше написан по умолчанию (D), и мне нравится остальная часть предлагаемого вами решения. – phillip

+0

@phillip - 'new D()' и 'default (D)' полностью разные - 'default (D)' равно null, если 'D' - тип класса, а 'zero' - это структура. – Lee

+0

В вашем третьем блоке кода без ограничения new() метод не обязательно должен быть общим. – lukegravitt

1

Используйте параметр по умолчанию:

public GridViewColumn<T> Column<D,T>(string HeaderText, D decorator = null) 
    where D : IColumnDecorator, class, new() 
+0

Спасибо ShadowCat7, теперь, как я могу назвать метод? Просто поставьте нуль как второй параметр? – Liming

+0

Параметры по умолчанию позволяют не добавлять второй параметр. Вы можете вызвать его, указав только строку и параметры типа. – ShadowCat7

1

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

public GridViewColumn<T> Column(String HeaderText, IColumnDecorator decorator) 
     { 
      GridViewColumn<T> column = new GridViewColumn<T>(); 
      column.HeaderText = HeaderText; 
      if(decorator ==null) 
      { 
       column.Decorator = new DefaultColumnDecorator(); 
      } 
      else{ 
       column.Decorator = decorator; 
      } 
      return column; 
     } 

Обоснованием здесь:. http://en.wikipedia.org/wiki/Dependency_injection

+0

Используйте нулевой оператор коалесценции и сделайте декоратор дополнительным, но это хороший подход. – lukegravitt

-1

Я вижу две вещи, которые вы пропали без вести. Один из них - это параметр по умолчанию decorator = null, а другой - default(T). Я переписал ваши данные следующим образом, но я не могу проверить это, очевидно, должен быть близок.

public GridViewColumn<TResult> Column<TColumn>(string HeaderText, TColumn decorator = null) where TColumn : IColumnDecorator, new() 
{ 
    GridViewColumn<TResult> column = new GridViewColumn<TResult>(); 
    column.HeaderText = HeaderText; 
    column.Decorator = decorator == null ? new DefaultColumnDecorator() : default(TColumn); 

    return column; 
} 
+0

philip, как я могу назвать этот код, если я хочу, чтобы декоратор был либо факультативным, либо нулевым? Я попытался указать ... Столбец («Текст заголовка», null), он говорит, что попробуйте явно указать использование. – Liming

+0

Столбец («HeaderText») - это все, что вам нужно сделать, потому что второй параметр уже указан. – phillip

+0

Вы должны заменить назначение 'Decorator' чем-то вроде' column.Decorator = decorator ?? new DefaultColumnDecorator(); ', поскольку в настоящее время вы назначаете null (если D - тип класса), если вызывающий объект предоставляет« декоратор ». – Lee

0

После игры с некоторыми вариантами я сделал образец, который работает со следующим кодом:

public GridViewColumn<TResult> Column<TColumn>(string HeaderText, TColumn decorator = null) where TColumn : class, IColumnDecorator 
{ 
    GridViewColumn<TResult> column = new GridViewColumn<TResult>(); 
    column.HeaderText = HeaderText; 

    if(decorator == null) 
    { 
     column.Decorator = new DefaultColumnDecorator(); 
    } 
    else 
    { 
     column.Decorator = decorator; 
    }  

    return column; 
} 

Для того, чтобы сделать эту работу, Вы должны учитывать следующее:

  • Вы необходимо добавить ограничение класса, чтобы определить свой параметр как null.
  • Вы не должны использовать по умолчанию (TColumn), так как он будет возвращать null из-за ограничения класса.
  • По какой-то причине, если вы используете синтаксис «?:», Компилятор не соглашается с тем, что вы создаете экземпляр типа DefaultColumnDecorator, но если вы используете регулярный оператор if, он работает.
  • Кажется, для этого не требуется ограничение new().

В моем примере я был в состоянии вызвать этот метод в следующих двух направлениях с тем же результатом:

@Model.[IEnumerable].Grid(grid=>{ 
     .. 
     ... 
     grid.columns(
     grid.Column<MyOwnColumnDecorator>("FirstColumn",null); 
    ) 
}); 

@Model.[IEnumerable].Grid(grid=>{ 
     .. 
     ... 
     grid.columns(
     grid.Column<MyOwnColumnDecorator>("FirstColumn"); 
    ) 
}); 

Успехов!

+0

Ничего себе, спасибо Серхио! Это почти тот же код, что и у меня сейчас. Проблема, о которой я забыл упомянуть, заключается в том, что в приведенном выше коде «MyOwnColumnDecorator» должен быть необязательным и нужен только в том случае, если у вас есть пользовательский класс, который реализует IColumnDecorator. Извините, я плохо спрашиваю. – Liming

0

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

public GridViewColumn<T> Column(string HeaderText, Func<IColumnDecorator> decoratorGenerator) 
{ 
    GridViewColumn<T> column = new GridViewColumn<T>(); 
    column.HeaderText = HeaderText; 
    column.Decorator = decoratorGenerator != null ? decoratorGenerator() 
    : new DefaultColumnDecorator() ; 
    return column; 
} 
+0

Спасибо, Дэвид. Причина, по которой я не хочу этого подхода, заключается в том, что я не хочу, чтобы конечным пользователям было сложно использовать его, поэтому после всех тестов/трейлов я предпочитаю подход Ли. В любом случае, спасибо. Очень ценю это. – Liming

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