может ли динамическая переменная C # ссылаться на статический тип? - PullRequest
1 голос
/ 23 июня 2010

Я использую стороннюю сборку, которая предоставляет сервисы через статический класс:

Foo.Bar.StaticLibraryClass.Start();
var x = Foo.Bar.StaticLibraryClass.GetSomeStuff();
Foo.Bar.StaticLibraryClass.Stop();

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

dynamic lib = new Foo.Bar.NotStaticLibraryClass();
lib.Start();
var x = lib.GetSomeStuff();
lib.Stop();

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

dynamic lib = /* ??????? */
lib.Start();
var x = lib.GetSomeStuff();
lib.Stop();

(Почему я хочу использовать переменную dynamic для доступа к совершенно хорошему типу .NET? На самом деле существует несколько версий библиотеки DLL, и я должен определить и загрузить соответствующую в время выполнения. Разные DLL предоставляют одинаковые имена типов и методов, но они наследуются от любого общего интерфейса. Поэтому, если я найду способ использовать динамическую типизацию, это избавит меня от написания большого количества кода отражения для использования DLL 'методы.)

Ответы [ 3 ]

0 голосов
/ 24 июня 2010

Извините, C # dynamic не поддерживает это использование напрямую.Чтобы вызвать метод класса в C #, вы должны указать имя типа в исходном коде напрямую.И чтобы сделать это, вы должны ссылаться на сборку.динамический не меняет этого.

динамический делает диспетчеризацию методов класса, когда это необходимо (например, когда у вас есть динамический аргумент), но даже в этих случаях ограничение выше остается.*

Если целевые типы предоставляют экземпляр, который вы можете поместить в динамическую переменную, то все будет в порядке.Если бы вы предоставили такой экземпляр, все будет в порядке.В качестве альтернативы, если ваше сердце настроено на динамику, вы можете написать свой собственный IDynamicMetaObjectProvider, который динамически оборачивает эти методы класса с учетом System.Type.Это был бы поучительный проект, если вы хотите узнать о DLR, по крайней мере.

0 голосов
/ 02 апреля 2015

Используйте магию dynamic:

using System;
using System.Dynamic;
using System.Reflection;

public class StaticInvoker : DynamicObject
{
    readonly BindingFlags flags;
    readonly Type type;

    public StaticInvoker(Type staticType) : this(staticType, false)
    {

    }

    public StaticInvoker(Type staticType, bool nonPublic)
    {
        type = staticType;
        flags = BindingFlags.Static | BindingFlags.Public | (nonPublic ? BindingFlags.NonPublic : 0);
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        try{
            result = type.InvokeMember(binder.Name, flags | BindingFlags.GetField | BindingFlags.GetProperty, null, null, null);
            return true;
        }catch(TargetInvocationException e)
        {
            throw e.InnerException;
        }catch(MissingMemberException)
        {
            result = null;
            return false;
        }
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        try{
            type.InvokeMember(binder.Name, flags | BindingFlags.SetField | BindingFlags.SetProperty, null, null, new[]{value});
            return true;
        }catch(TargetInvocationException e)
        {
            throw e.InnerException;
        }catch(MissingMemberException)
        {
            return false;
        }
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        try{
            result = type.InvokeMember(binder.Name, flags | BindingFlags.InvokeMethod, null, null, args);
            return true;
        }catch(TargetInvocationException e)
        {
            throw e.InnerException;
        }catch(MissingMemberException)
        {
            result = null;
            return false;
        }
    }
}

dynamic lib = new StaticInvoker(typeof(Foo.Bar.StaticLibraryClass));

Поддерживает все основные операции.

0 голосов
/ 23 июня 2010

c # / vb.net и т. Д. Являются статически типизированными языками.Следовательно, если у вас есть тип, у которого нет метода Start, код не будет компилироваться.

dynamic ключевое слово устраняет разрыв между статическими языками и динамическими языками.
, т.е.метод не существует, проверяется во время выполнения в случае динамических языков.

Из вашего примера Start, Stop, 'GetSomeStuff method exists and your code is aware of it. Moreover, dynamic` не имеет ничего общего с динамической загрузкой сборки.

Я думаю, вам нужен какой-томодель типа «плагин / провайдер», при которой у вас будет базовый интерфейс, который будет подтверждать ваш класс (ы) реализации.

например,

interface IService
{
   void Start();
   void Stop();
   int GetSomeStuff();
}

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

Внедрение / инверсия зависимости - это концепция, которая приходит мне в голову, который, я думаю, должен служить тому, что вы ищете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...