2013-02-20 81 views
2

我遇到了一个问题,即要让我的ServiceKnownType属性中指定的帮助器方法运行。为了简单起见,我有两个程序集:一个具有我的服务接口和用于数据协定的接口,另一个具有我的服务实现和具体的数据协定。无法让我的服务调用ServiceKnownType帮助器方法

这是我的服务及其实施的简化/精简版本。

MyService.Interface.dll

// IMyService.cs 
[ServiceContract] 
IMyService 
{ 
    [OperationContract] 
    IList<IMyData> GetData(); 
} 

// IMyData.cs 
public interface IMyData 
{ 
    int Foo { get; set; } 
} 

MyService.dll(具有到MyService.Interface.dll的引用)

// MyService.svc.cs 
public class MyService: IMyService 
{ 
    public IList<IMyData> GetData() 
    { 
     // Instantiate List<IMyData>, add a new MyData to the list 
     // return the List<IMyData>. 
    } 
} 

// MyData.cs 
[DataContract] 
public class MyData : IMyData 
{ 
    [DataMember] 
    public int Foo { get; set; } 
} 

问题的根源在于,序列化GetData()的结果,服务必须被通知有关具体MyData类和具体List<IMyData>泛型类,因为服务e定义使用接口类型而不是具体类型。

简单的答案是装饰IMyService与:(并且不能是由于循环引用)

[ServiceKnownType(typeof(MyData))] 
[ServiceKnownType(typeof(List<IMyData>))] 

然而,MyData在未内MyService.Interface.dll引用的组件被定义

我的下一个想法是对的MyService本身使用的ServiceKnownType的“helper方法”的形式:

[ServiceKnownType("GetDataContracts", MyService)] 
public class MyService: IMyService 
{ 
    public static IEnumerable<Type> GetDataContracts(ICustomeAttributeProvider provider) 
    { 
     // create a List<Type>, add MyData to it, and return it. 
    } 
    //... 
} 

至于我可以看到,除了GetDataContracts永远不会被调用。我试着将它移动到一个单独的静态类(与MyService并行并嵌套在它内部),但绝不能在这里获得一个断点。

编辑:我也想说,通过web.config添加已知类型不起作用,因为我有泛型类型不能添加这种方式。你只能通过web.config中添加简单的,具体类型:

<knownType type="TypeName, Assembly" /> 

我的具体List<IMyData>没有在装配中完全限定的类型名称。

回答

1

固定。答案是使用helper方法形式将ServiceKnownType添加到服务接口,而不是服务实现,并添加一个帮助类,该类反映我需要的类型,而不是通过引用代码中的具体类型来添加它们。 (回想一下,我不能这样做,因为我不能引用该程序集添加。)

[ServiceContract] 
[ServiceKnownType("GetDataContractTypes", typeof(MyServiceHelper))] 
public interface IMyService 
{ ... } 

而且我添加了一个新的MyServiceHelper类Nightingale.Interface,但它不是公共所以我不关心不必要地暴露一个我只想成为“纯粹”接口的程序集。

// Not public outside of this assembly. 
static class MyServiceHelper 
{ 
    public static IEnumerable<Type> GetDataContractTypes(ICustomAttributeProvider paramIgnored) 
    { 
     // Get the assembly with the concrete DataContracts. 
     Assembly ass = Assembly.Load("MyService"); // MyService.dll 
     // Get all of the types in the MyService assembly. 
     var assTypes = ass.GetTypes(); 
     // Create a blank list of Types. 
     IList<Type> types = new List<Type>(); 
     // Get the base class for all MyService data contracts 
     Type myDataContractBase = ass.GetType("MyDataContractBase", true, true); 
     // Add MyService's data contract Types. 
     types.Add(assTypes.Where(t => t.IsSubclassOf(myDataContractBase))); 
     // Add all the MyService data contracts to the service's known types so they can be serialized. 
     return types; 
    } 
} 

这个特殊的解决方案适用于我,因为我所有的DataContract类扩展了一个公共基类。在我的情况下,可以重新加载所有具有DataContract属性的程序集中的所有类型,这会导致相同的集合。