Десериализовать строку из шаблона URI в параметр типа операции - PullRequest
1 голос
/ 21 ноября 2011

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

../MyClass1/some/further/spec
../MyClass2/some/further/spec

Я хочу, чтобы мои шаблоны URI выглядели примерно так:

/{type}/some/further/{info}

И моя операция будет выглядеть примерно так:

public void ClassSpecificOfSomeFurtherSpec(Type type, string info)

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

public void ClassSpecificOfSomeFurtherSpec<type>(string info)

Проблема здесь в том, что вход для класса - это короткое имя типа, а не полное имя, что означает Type.GetType (class, true, true)не сработаетЕсли бы я мог использовать это в своей пользовательской десериализации, и все было бы хорошо.Но так как этого не произойдет, я не хочу жестко кодировать свое пространство имен в моей общей десериализации, поскольку это сделает его совершенно неуниверсальным.

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

У меня такое чувство, что я слишком усложняю вещи.Есть ли простой способ сделать то, что я упустил, или какая-то действительно убедительная причина, почему я не должен так обобщать свои услуги?

Суть в том, что я хочу избежать этогокод для каждой отдельной операции:

public Response ClassSpecificOfSomeFurtherSpec(string type, string spec)
{
    Type theType = Type.GetType("My.NameSpaced."+type, true, true);
    //.. and the stuff that does things
}

Update1

Итак, я нашел этот замечательный пост в блоге Карлоса, описывающий, как добавить опцию превращения IParameterInspectorв улучшенную версию, которая также может изменять параметры.В блоге он только изменяет возвращаемые значения.Что я хотел сделать, это изменить входное значение.Итак, я добавил эту возможность и добавил свой класс-модификатор:

public class EntityParameterModifier : IParameterModifier
{
    public OperationDescription Description { get; private set; }

    public EntityParameterModifier(OperationDescription description)
    {
        Description = description;
    }

    public object BeforeCall(string operationName, ref object[] inputs)
    {
        var parts = Description.Messages[0].Body.Parts;
        for (int i = 0; i < parts.Count; i++)
        {
            if (parts[i].Type == typeof(Type) && inputs[i].GetType() == typeof(string))
                inputs[i] = EntityStringToType((string)inputs[i]);
        }

        return null;
    }

    public void AfterCall(string operationName, object[] outputs, ref object returnValue, object correlationState) { }

    private Type EntityStringToType(string entityString)
    {
        Assembly assembly = Assembly.GetAssembly(typeof(Entity));
        Type type = (from t in assembly.GetTypes()
                     where t.Name == entityString || t.FullName == entityString
                     select t).SingleOrDefault<Type>();
        return type;
    }
}

Но, конечно, они добавили несколько блоков, чтобы помешать вам делать такие вещи:

[InvalidOperationException: Operation 'ClassSpecificOfSomeFurtherSpec' in contract 
'IMyServiceContract' has a path variable named 'type' which does not have type 'string'.
Variables for UriTemplate path segments must have type 'string'.]
System.ServiceModel.Dispatcher.UriTemplateClientFormatter.Populate(Dictionary`2& pathMapping, Dictionary`2& queryMapping, Int32& totalNumUTVars, UriTemplate& uriTemplate, OperationDescription operationDescription, QueryStringConverter qsc, String contractName) +1128

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

Ответы [ 2 ]

1 голос
/ 21 ноября 2011

Возможно, это так, но вам придется написать свой собственный IDispatchMessageFormatter, который знает о UriTemplates и знает, как преобразовывать строки в типы - не простая задача. Это становится проще с проектом веб-API WCF (см. http://wcf.codeplex.com),, где у вас больше гибкости по сравнению с поставщиками параметров.

0 голосов
/ 21 ноября 2011

Один из способов добиться этого - загрузить все типы в память, а затем попытаться найти тип, имя которого соответствует строке, и создать этот тип. Но вам также нужно убедиться, что один и тот же тип не существует в разных пространствах имен с одинаковыми именами.

Ниже приведен пример кода, который я написал для поиска типов в исполняемой сборке:

Assembly ass = Assembly.GetExecutingAssembly();
            foreach (Type t in ass.GetTypes())
            {
                Console.WriteLine(t.Name);
                Console.WriteLine(t.Namespace);
                Console.WriteLine(t.FullName);
                Console.WriteLine("----End of type----");
            }

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

Надеюсь, это поможет вам в некоторой степени.

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