var myService = new MyService(A.Fake<ISevice1>(), new Sevice2(), A.Fake<ISevice3>(), A.Fake<ISevice4>(), A.Fake<ISevice5>(), A.Fake<ISevice6>())
var myService = GetInstance<MyService>().With(new Sevice2()).Subject;
public ObjectBuilder<T> With<TParam>(TParam param) { _overriddenTypes.Add(typeof(TParam), param); return this; }
private T Build() { var type = typeof(T); var constructors = type.GetConstructors().Where(x => x.IsPublic).ToList(); var parameterizedConstructors = constructors.Where(x => x.GetParameters().Any()).ToList(); if (!parameterizedConstructors.Any()) { // } var constructor = parameterizedConstructors.Single(); var parametersType = constructor.GetParameters().Select(x => x.ParameterType).ToList(); var arguments = parametersType.Select(x => _overriddenTypes.ContainsKey(x) ? _overriddenTypes[x] : Create.Fake(x)).ToArray(); return GetObject(constructor, parametersType, arguments); }
private T GetObject(ConstructorInfo constructor, List<Type> constructorParametersType, object[] arguments) { if (_objectCreatorCache != null) { return _objectCreatorCache(arguments); } var creator = GetObjectCreator(constructor, constructorParametersType); _objectCreatorCache = creator; return creator(arguments); }
public class ObjectBuilder<T> {...}
private static Func<object[], T> _objectCreatorCache;
Activator.CreateInstance<T>();
private Func<object[], T> GetObjectCreator(ConstructorInfo constructor, List<Type> constructorParametersType) { var param = Expression.Parameter(typeof(object[]), "parameters"); var argsExpressions = new Expression[constructorParametersType.Count]; for (var index = 0; index < constructorParametersType.Count; index++) { var constantIndex = Expression.Constant(index); var paramAccessorExp = Expression.ArrayIndex(param, constantIndex); var paramCastExp = Expression.Convert(paramAccessorExp, constructorParametersType[index]); argsExpressions[index] = paramCastExp; } var newExpression = Expression.New(constructor, argsExpressions); var lambda = Expression.Lambda(typeof(Func<object[], T>), newExpression, param); return (Func<object[], T>)lambda.Compile(); }
public class ObjectBuilder<T> { private static Func<object[], T> _objectCreatorCache; private readonly Dictionary<Type, object> _overriddenTypes; private readonly Lazy<T> _subject; public ObjectBuilder() { _overriddenTypes = new Dictionary<Type, object>(); _subject = new Lazy<T>(Build); } public T Subject => _subject.Value; public ObjectBuilder<T> With<TParam>(TParam param) { if (_subject.IsValueCreated) { throw new Exception("Can't change builder options after first call to Object. Please create new one"); } _overriddenTypes.Add(typeof(TParam), param); return this; } private T Build() { var type = typeof(T); var constructors = type.GetConstructors().Where(x => x.IsPublic).ToList(); var parameterizedConstructors = constructors.Where(x => x.GetParameters().Any()).ToList(); if (!parameterizedConstructors.Any()) { // } var constructor = parameterizedConstructors.Single(); var constructorParametersType = constructor.GetParameters().Select(x => x.ParameterType).ToList(); var arguments = constructorParametersType.Select(x => _overriddenTypes.ContainsKey(x) ? _overriddenTypes[x] : Create.Fake(x)).ToArray(); return GetObject(constructor, constructorParametersType, arguments); } private T GetObject(ConstructorInfo constructor, List<Type> constructorParametersType, object[] arguments) { if (_objectCreatorCache != null) { return _objectCreatorCache(arguments); } var creator = GetObjectCreator(constructor, constructorParametersType); _objectCreatorCache = creator; return creator(arguments); } private Func<object[], T> GetObjectCreator(ConstructorInfo constructor, List<Type> constructorParametersType) { var param = Expression.Parameter(typeof(object[]), "parameters"); var argsExpressions = new Expression[constructorParametersType.Count]; for (var index = 0; index < constructorParametersType.Count; index++) { var constantIndex = Expression.Constant(index); var paramAccessorExp = Expression.ArrayIndex(param, constantIndex); var paramCastExp = Expression.Convert(paramAccessorExp, constructorParametersType[index]); argsExpressions[index] = paramCastExp; } var newExpression = Expression.New(constructor, argsExpressions); var lambda = Expression.Lambda(typeof(Func<object[], T>), newExpression, param); return (Func<object[], T>)lambda.Compile(); } }
Source: https://habr.com/ru/post/350688/
All Articles