- FrictSLUnitTest.zip
- README.txt
- Sample.Silverlight.WCF.sln
- Source
- Sample.Silverlight.WCF.Tests.Clumsy.Web
- Sample.Silverlight.WCF.Tests.Clumsy
- Sample.Silverlight.WCF.Tests
- Sample.Silverlight.WCF.Web
- Sample.Silverlight.WCF
- Tools
- NUnit
- nunit.framework.dll
- nunit.silverlight.dll
- Rhino.Mocks
- Castle.Core-Silverlight.dll
- Castle.DynamicProxy-Silverlight.dll
- Rhino.Mocks 3.5.Silverlight.dll
|
#region Author
//// Yevhen Bobrov, http://blog.xtalion.com
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.ServiceModel;
namespace Sample.Silverlight.WCF.Infrastructure.Services
{
public class AsyncServiceInterfaceGenerator
{
readonly ModuleBuilder module;
readonly Type syncInterface;
TypeBuilder asyncInterface;
public AsyncServiceInterfaceGenerator(ModuleBuilder module, Type syncInterface)
{
this.module = module;
this.syncInterface = syncInterface;
}
public Type Generate()
{
DefineAsyncInterfaceType();
DefineAsyncMethodPairs();
return asyncInterface.CreateType();
}
void DefineAsyncInterfaceType()
{
string asyncInterfaceName = syncInterface.Namespace + "." + syncInterface.Name + "Async";
asyncInterface = module.DefineType(asyncInterfaceName,
TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract);
asyncInterface.SetCustomAttribute(CreateAttribute<ServiceContractAttribute>("Name", syncInterface.Name));
}
void DefineAsyncMethodPairs()
{
foreach (MethodInfo method in GetOperationContractMethods())
{
DefineAsyncMethodPair(method);
}
}
void DefineAsyncMethodPair(MethodInfo method)
{
DefineBeginMethod(method);
DefineEndMethod(method);
}
void DefineBeginMethod(MethodInfo method)
{
List<Type> parameterTypes = CollectParameterTypes(method);
MethodBuilder methodBuilder = asyncInterface.DefineMethod("Begin" + method.Name, MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual,
typeof(IAsyncResult), parameterTypes.ToArray());
DefineParameterNames(method, methodBuilder);
DefineOperationContractAttribute(methodBuilder);
DefineFaultContractAttribute(method, methodBuilder);
}
static void DefineParameterNames(MethodInfo syncMethod, MethodBuilder asyncMethod)
{
int position = 1;
foreach (ParameterInfo parameter in syncMethod.GetParameters())
{
asyncMethod.DefineParameter(position++, ParameterAttributes.In, parameter.Name);
}
}
static List<Type> CollectParameterTypes(MethodInfo method)
{
return new List<Type>(method.GetParameters().Select(parameter => parameter.ParameterType))
{
typeof(AsyncCallback), typeof(object)
};
}
static void DefineOperationContractAttribute(MethodBuilder methodBuilder)
{
methodBuilder.SetCustomAttribute(CreateAttribute<OperationContractAttribute>("AsyncPattern", true));
}
static void DefineFaultContractAttribute(MethodInfo method, MethodBuilder methodBuilder)
{
if (!HasAttribute(method, typeof(FaultContractAttribute)))
return;
var faultContract = (FaultContractAttribute)method.GetCustomAttributes(typeof(FaultContractAttribute), true)[0];
var attributeBulder = new CustomAttributeBuilder(
typeof(FaultContractAttribute).GetConstructor(new[] { typeof(Type) }), new object[] { faultContract.DetailType });
methodBuilder.SetCustomAttribute(attributeBulder);
}
void DefineEndMethod(MethodInfo method)
{
asyncInterface.DefineMethod("End" + method.Name, MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual,
method.ReturnType, new[] { typeof(IAsyncResult) });
}
IEnumerable<MethodInfo> GetOperationContractMethods()
{
return syncInterface.GetMethods().Where(method => HasAttribute(method, typeof(OperationContractAttribute)));
}
static bool HasAttribute(MethodInfo method, Type attribute)
{
return method.GetCustomAttributes(attribute, true).Length > 0;
}
static CustomAttributeBuilder CreateAttribute<TAttribute>(string property, object value) where TAttribute : Attribute
{
Type attributeType = typeof(TAttribute);
return new CustomAttributeBuilder(attributeType.GetConstructor(new Type[0]), new object[0],
new[] { attributeType.GetProperty(property) }, new[] { value });
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.