DefaultClayActivator.cs 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Dynamic;
  4. using System.Linq.Expressions;
  5. using Castle.DynamicProxy;
  6. namespace Masuit.Tools.Dynamics;
  7. internal class DefaultClayActivator : IClayActivator
  8. {
  9. private static readonly IProxyBuilder _builder = new DefaultProxyBuilder();
  10. public dynamic CreateInstance(Type baseType, IEnumerable<IClayBehavior> behaviors, IEnumerable<object> arguments)
  11. {
  12. var isDynamicMetaObjectProvider = typeof(IDynamicMetaObjectProvider).IsAssignableFrom(baseType);
  13. var isClayBehaviorProvider = typeof(IClayBehaviorProvider).IsAssignableFrom(baseType);
  14. if (isDynamicMetaObjectProvider && isClayBehaviorProvider)
  15. {
  16. var constructorArguments = new object[]
  17. {
  18. behaviors
  19. };
  20. return Activator.CreateInstance(baseType, constructorArguments);
  21. }
  22. Func<object, object> contextualize = proxy => proxy;
  23. var options = new ProxyGenerationOptions();
  24. var constructorArgs = new List<object>();
  25. if (!isClayBehaviorProvider)
  26. {
  27. var mixin = new MixinClayBehaviorProvider(behaviors);
  28. options.AddMixinInstance(mixin);
  29. constructorArgs.Add(mixin);
  30. }
  31. if (!isDynamicMetaObjectProvider)
  32. {
  33. var mixin = new MixinDynamicMetaObjectProvider();
  34. options.AddMixinInstance(mixin);
  35. constructorArgs.Add(mixin);
  36. var prior = contextualize;
  37. contextualize = proxy =>
  38. {
  39. mixin.Instance = proxy;
  40. return prior(proxy);
  41. };
  42. }
  43. var proxyType = _builder.CreateClassProxyType(baseType, Type.EmptyTypes, options);
  44. constructorArgs.Add(new IInterceptor[]
  45. {
  46. new ClayInterceptor()
  47. });
  48. if (arguments != null)
  49. {
  50. constructorArgs.AddRange(arguments);
  51. }
  52. return contextualize(Activator.CreateInstance(proxyType, constructorArgs.ToArray()));
  53. }
  54. private class MixinClayBehaviorProvider : IClayBehaviorProvider
  55. {
  56. private readonly IClayBehavior _behavior;
  57. public MixinClayBehaviorProvider(IEnumerable<IClayBehavior> behaviors)
  58. {
  59. _behavior = new ClayBehaviorCollection(behaviors);
  60. }
  61. IClayBehavior IClayBehaviorProvider.Behavior => _behavior;
  62. }
  63. private class MixinDynamicMetaObjectProvider : IDynamicMetaObjectProvider
  64. {
  65. public object Instance { get; set; }
  66. DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression expression)
  67. {
  68. return new ClayMetaObject(Instance, expression);
  69. }
  70. }
  71. }