Last active
July 20, 2017 06:40
-
-
Save sakapon/5d61eedc9580f6dba2bbefcb4373839e to your computer and use it in GitHub Desktop.
ProxySample/CrossCuttingConsole/CrossCuttingProxy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.Remoting.Messaging; | |
using System.Transactions; | |
namespace CrossCuttingConsole | |
{ | |
[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)] | |
public abstract class AspectAttribute : Attribute | |
{ | |
public abstract IMethodReturnMessage Invoke(Func<IMethodReturnMessage> baseInvoke, MarshalByRefObject target, IMethodCallMessage methodCall); | |
} | |
public class TraceLogAttribute : AspectAttribute | |
{ | |
public override IMethodReturnMessage Invoke(Func<IMethodReturnMessage> baseInvoke, MarshalByRefObject target, IMethodCallMessage methodCall) | |
{ | |
var methodInfo = $"{methodCall.MethodBase.DeclaringType.Name}.{methodCall.MethodName}({string.Join(", ", methodCall.InArgs)})"; | |
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: Begin: {methodInfo}"); | |
var result = baseInvoke(); | |
if (result.Exception == null) | |
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: Success: {methodInfo}"); | |
else | |
{ | |
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: Error: {methodInfo}"); | |
Console.WriteLine(result.Exception); | |
} | |
return result; | |
} | |
} | |
public class TransactionScopeAttribute : AspectAttribute | |
{ | |
public TransactionOptions TransactionOptions { get; } | |
public TransactionScopeOption TransactionScopeOption { get; } | |
public TransactionScopeAttribute( | |
IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, | |
double timeoutInSeconds = 30, | |
TransactionScopeOption scopeOption = TransactionScopeOption.Required) | |
{ | |
TransactionOptions = new TransactionOptions | |
{ | |
IsolationLevel = isolationLevel, | |
Timeout = TimeSpan.FromSeconds(timeoutInSeconds), | |
}; | |
TransactionScopeOption = scopeOption; | |
} | |
public override IMethodReturnMessage Invoke(Func<IMethodReturnMessage> baseInvoke, MarshalByRefObject target, IMethodCallMessage methodCall) | |
{ | |
using (var scope = new TransactionScope(TransactionScopeOption, TransactionOptions)) | |
{ | |
var result = baseInvoke(); | |
scope.Complete(); | |
return result; | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Reflection; | |
using System.Runtime.Remoting; | |
using System.Runtime.Remoting.Activation; | |
using System.Runtime.Remoting.Messaging; | |
using System.Runtime.Remoting.Proxies; | |
namespace CrossCuttingConsole | |
{ | |
public class CrossCuttingProxy : RealProxy | |
{ | |
public static T CreateProxy<T>() where T : MarshalByRefObject, new() | |
{ | |
return (T)new CrossCuttingProxy(new T()).GetTransparentProxy(); | |
} | |
public MarshalByRefObject Target { get; private set; } | |
// For non-ContextBoundObject. | |
internal CrossCuttingProxy(MarshalByRefObject target) : base(target.GetType()) | |
{ | |
Target = target; | |
} | |
// For ContextBoundObject. | |
internal CrossCuttingProxy(Type classToProxy) : base(classToProxy) | |
{ | |
} | |
public override IMessage Invoke(IMessage msg) | |
{ | |
if (msg is IConstructionCallMessage constructionCall) | |
return InvokeConstructor(constructionCall); | |
if (msg is IMethodCallMessage methodCall) | |
return InvokeMethod(methodCall); | |
throw new InvalidOperationException(); | |
} | |
IConstructionReturnMessage InvokeConstructor(IConstructionCallMessage constructionCall) | |
{ | |
var constructionReturn = InitializeServerObject(constructionCall); | |
Target = GetUnwrappedServer(); | |
SetStubData(this, Target); | |
return constructionReturn; | |
} | |
IMethodReturnMessage InvokeMethod(IMethodCallMessage methodCall) | |
{ | |
Func<IMethodReturnMessage> baseInvoke = () => RemotingServices.ExecuteMessage(Target, methodCall); | |
var newInvoke = methodCall.MethodBase.GetCustomAttributes<AspectAttribute>(true) | |
.Reverse() | |
.Aggregate(baseInvoke, (f, a) => () => a.Invoke(f, Target, methodCall)); | |
return newInvoke(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment