2010-06-04 4 views
38

С новыми динамическими возможностями в .NET 4.0 кажется, что должно быть возможно динамическое внедрение интерфейса, например. Дано:Динамическое внедрение интерфейса в .NET 4.0 (C#)

public interface IFoo 
{ 
    string Bar(int baz); 
} 

public class Foo : IFoo 
{ 
    public string Bar(int baz) { return baz.ToString(); } 
} 

public class Proxy : IDynamicMetaObjectProvider 
{ 
    private readonly object target; 

    public Proxy(object target) { this.target = target; } 

    // something clever goes here 
} 

Тогда я надеюсь, что есть какой-то способ, чтобы сделать возможным написать:

dynamic proxy = new Proxy(new Foo()); 
IFoo fooProxy = (IFoo)proxy; // because the target object implements it 
string bar = fooProxy.Bar(123); // delegates through to the target implementation 

Но, пока я не уверен, что заменить // something clever goes here с.

Итак, мои вопросы:

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

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

  3. Есть ли какие-либо ресурсы, которые помогут указать мне в правильном направлении для реализации чего-то вроде это? Или даже образцы, где это уже сделано, что я могу использовать в качестве отправной точки?

+0

Где код, реализующий методы интерфейса? –

ответ

13

Насколько я знаю, без ручного вмешательства невозможно вручную написать или сгенерировать код, который пересылает члены интерфейса в завернутый экземпляр. Если вы хотите получить поддержку Microsoft для такого рода вещей, возможно, вам захочется рассмотреть вопрос о проведении голосования по адресу https://connect.microsoft.com/VisualStudio/feedback/details/526307/add-automatic-generation-of-interface-implementation-via-implementing-member .

+1

Эта страница ссылки не найдена ... –

+0

Я думаю, что обратная связь перенесена на https://visualstudio.uservoice.com/forums/121579-visual-studio-ide/suggestions/2099133-add-auto-implement-feature-to- c-language, но это закрыто. Запросы функций C# теперь должны перейти на https://github.com/dotnet/csharplang –

7

Я думаю, что я написал библиотеку, которая делает то, что вы хотите ... Это называется DynamicWrapper (на CodePlex), и он будет автоматически обернуть класс так он реализует интерфейс. Is this what you want?

+2

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

3

Явное литье, as и is терпят неудачу из сравнения типа будет против прокси базового класса, но неявной гипсе могут вызвать DynamicObject.TryConvert, так что вы можете вернуть внутренний объект-вместо динамического объекта.
TryConvert MSDN Documentation

Хотя приведенный ниже код работает, это не делегирование интерфейса как таковое, а только воздействие внутреннего состояния. Похоже, вы можете искать что-то вроде шаблона перехвата, такого как DynamicWrapper Брайана.

dynamic wrapper = new Proxy(new Foo()); 
IFoo foo = wrapper; 
foo.Bar(); 

class Proxy : DynamicObject 
{ 
    ... 

    public override bool TryConvert(ConvertBinder binder, out object result) 
    { 
     Type bindingType = binder.Type; 
     if (bindingType.IsInstanceOfType(target)) 
     { 
      result = target; 
      return true; 
     } 
     result = null; 
     return false; 

    } 

} 
+0

+1, но я не последовал: почему явное кастинг заканчивается? Любопытно, потому что 'ConvertBinder' имеет свойство' Explicit' для запроса на это. –

+0

Жордану кажется, что в отличие от неявного синтаксиса кастинга, который генерирует вызов Binder.Convert в сгенерированном IL, синтаксис «is» и «as» пропускает тестирование для преобразования. например, в q), например, тип Foo! = type Proxy. – stephbu

38

Рамка с открытым исходным кодом Impromptu-Interface предназначена для этого. Он генерирует кэшированный легкий прокси-сервер со статическим интерфейсом и использует dlr для перенаправления вызова на исходный объект.

using ImpromptuInterface; 

public interface ISimpeleClassProps 
{ 
    string Prop1 { get; } 

    long Prop2 { get; } 

    Guid Prop3 { get; } 
} 

-

dynamic tOriginal= new ExpandoObject(); 
tOriginal.Prop1 = "Test"; 
tOriginal.Prop2 = 42L; 
tOriginal.Prop3 = Guid.NewGuid(); 

ISimpeleClassProps tActsLike = Impromptu.ActLike(tOriginal); 
+2

Какая отличная рамка. Я часто использовал это. –

+2

+1: удивительная библиотека – IAbstract

2

Дополняя ответ от @jbtule Я создал свой CustomActivator, который способен создать динамический объект во время выполнения и сделать его реализует нужный интерфейс. Я также использую Impromptu-Interface framework для этого.

Вызов прост:

CustomActivator.CreateInstance<MyInterface>(); 

Я положил его на github.

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