how to apply OperationContract to all methods in interface
Asked Answered
H

3

2

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

Headlong answered 10/9, 2013 at 14:25 Comment(0)
G
0

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);
    // ...
}
Gould answered 10/9, 2013 at 14:43 Comment(2)
is there any free tool for AOP, like PostShartp ?Headlong
@JohnSmith PostSharp has free license (not sure if adding attributes available in free edition). You can take a look on this AOP frameworks listGould
C
2

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.

Cannibal answered 10/9, 2013 at 14:30 Comment(1)
OK, I just hoped there is a way how to say explicitly each method is a part of my service contract. I think Microsoft should support such an option. Nevertheless - thanks :)Headlong
G
0

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);
    // ...
}
Gould answered 10/9, 2013 at 14:43 Comment(2)
is there any free tool for AOP, like PostShartp ?Headlong
@JohnSmith PostSharp has free license (not sure if adding attributes available in free edition). You can take a look on this AOP frameworks listGould
L
0

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).

Longley answered 3/2, 2015 at 9:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.