DefaultClayActivator.cs 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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(IEnumerable<IClayBehavior> behaviors) : IClayBehaviorProvider
  55. {
  56. IClayBehavior IClayBehaviorProvider.Behavior { get; } = new ClayBehaviorCollection(behaviors);
  57. }
  58. private class MixinDynamicMetaObjectProvider : IDynamicMetaObjectProvider
  59. {
  60. public object Instance { get; set; }
  61. DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression expression)
  62. {
  63. return new ClayMetaObject(Instance, expression);
  64. }
  65. }
  66. }