Подтвердить что ты не робот

Динамическое внедрение интерфейса в .NET 4.0 (С#)

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

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 на.

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

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

Для этого была создана инфраструктура opensource 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);

Ответ 3

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

Ответ 4

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

В то время как приведенный ниже код работает, это не делегирование интерфейса как таковое, а только воздействие внутреннего состояния. Похоже, вы можете искать что-то вроде шаблона перехвата, такого как Brian 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;

    }

}

Ответ 5

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

Вызов прост:

CustomActivator.CreateInstance<MyInterface>();

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