我有这个restfull服务,我希望能够调用某个命名空间或程序集中的所有类。而且我将需要知道它在操作中被调用的类型。简而言之,我想要一个允许这两者的模板:
../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的短名称,而不是FullName,这意味着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
因此,我发现Carlos的这个很好blog post描述了如何添加将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或相关的类来实现我想要的?
答案 0 :(得分:1)
可能是这样,但你必须编写自己的IDispatchMessageFormatter
,它既知道UriTemplates又知道如何在字符串和类型之间进行转换 - 这不是一件容易的事。使用WCF Web API项目(请参阅http://wcf.codeplex.com)可以更轻松地获得参数提供程序的灵活性。
答案 1 :(得分:0)
您可以实现的一种方法是将所有类型加载到内存中,然后尝试查找名称与字符串匹配的类型并创建该类型。但是,您还需要确保在具有相同名称的不同命名空间中不存在相同类型。
我编写的一些示例代码用于查找正在执行的程序集中的类型:
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----");
}
这不是一个确切的解决方案,只是为您提供在执行程序集中加载类型。
希望它在某种程度上对你有帮助。