Im creating a service contract in my wcf application and it contains a lot of methods.
I find it very annoying to write an OperationContract
attribute to all of them.
Is there any simple way how to say "every method in my ServiceContract
interface is an OperationContract
" ?
thank you
Yes, you can use AOP framework for that. E.g. with PostSharp:
[Serializable]
public sealed class AutoServiceContractAttribute : TypeLevelAspect, IAspectProvider
{
// This method is called at build time and should just provide other aspects.
public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
{
Type targetType = (Type)targetElement;
var introduceServiceContractAspect =
new CustomAttributeIntroductionAspect(
new ObjectConstruction(typeof(ServiceContractAttribute)
.GetConstructor(Type.EmptyTypes)));
var introduceOperationContractAspect =
new CustomAttributeIntroductionAspect(
new ObjectConstruction(typeof(OperationContractAttribute)
.GetConstructor(Type.EmptyTypes)));
// Add the ServiceContract attribute to the type.
yield return new AspectInstance(targetType, introduceServiceContractAspect);
// Add a OperationContract attribute to every relevant method.
var flags = BindingFlags.Public | BindingFlags.Instance;
foreach (MethodInfo method in targetType.GetMethods(flags))
{
if (!method.IsDefined(typeof(NotOperationContractAttribute), false))
yield return new AspectInstance(method, introduceOperationContractAspect);
}
}
}
This attribute used to mark methods which should not be operation contracts:
[AttributeUsage(AttributeTargets.Method)]
public sealed class NotOperationContractAttribute : Attribute
{
}
Now all you need to do is apply AutoServiceContract
attribute to service interface. That will add ServiceContract
attribute to interface, and all public methods will be marked with OperationContact
attribute (except those which have NotOperationContract
attribute):
[AutoServiceContract]
public interface IService1
{
public void Method1();
[NotOperationContact]
public string Method2);
public int Method3(int a);
// ...
}
No, you need to do it on each and every method. it defines an operation that is part of a service contract in a Service. There is a possibility that some of the methods are not intended for Exposing.
Spring.Net has built-in feature ServiceExporter
and all you need is such config:
<object id="MyServiceExporter" type="Spring.ServiceModel.ServiceExporter, Spring.Services">
<property name="TargetName" value="MyService" />
<property name="TypeAttributes">
<list>
<object type="System.ServiceModel.ServiceBehaviorAttribute, System.ServiceModel">
<property name="ConfigurationName" value="MyService"/>
</object>
</list>
</property>
</object>
<object id="MyService" singleton="false" type="Eluzzion.TOrder.Service.OrderExportService, Eluzzion.TOrder.Service" />
<object id="MyServiceHost" type="Spring.ServiceModel.Activation.ServiceHostFactoryObject, Spring.Services" lazy-init="false" >
<property name="TargetName" value="MyServiceExporter" />
</object>
For more details check documentation and this forum thread. You need to have service definition in app.config
called same as the Spring object: MyService
Next step will be to decorate all objects with DataContract
attribute. Any ideas? Not very good one is to use XmlSerializerFormat
attribute on service contracts (can be added by Spring too).