public CreationResult TryResolveDummyValue(Type typeOfDummy, LoopDetectingResolutionContext resolutionContext) { // Make sure we're not already resolving typeOfDummy. It may seem that we could skip this check when we have // a cached resolution strategy in strategyCache, but it's necessary in case multiple threads are involved and // typeOfDummy has a constructor that takes typeOfDummy as a parameter. // In that situation, perhaps this thread starts trying to resolve a Dummy using the constructor that takes a // typeOfDummy. Meanwhile another thread does the same thing, but gets more processing time and eventually fails to // use that constructor, but then it succeeds in making a typeOfDummy using a different constructor. Then the strategy // is cached. This thread sees the cached strategy, creates a typeOfDummy for the constructor parameter, and then // uses it to make the "outer" typeOfDummy. Then we'd have Dummies created via two different constructors, which // might have different behavior. This is essentially the problem that arose in issue 1639. if (!resolutionContext.TryBeginToResolve(typeOfDummy)) { return(CreationResult.FailedToCreateDummy(typeOfDummy, "Recursive dependency detected. Already resolving " + typeOfDummy + '.')); } try { return(this.strategyCache.TryGetValue(typeOfDummy, out ResolveStrategy cachedStrategy) ? cachedStrategy.TryCreateDummyValue(typeOfDummy, this, resolutionContext) : this.TryResolveDummyValueWithAllAvailableStrategies(typeOfDummy, resolutionContext)); } finally { resolutionContext.EndResolve(typeOfDummy); } }
public CreationResult CreateFake( Type typeOfFake, IProxyOptions proxyOptions, IDummyValueResolver resolver, LoopDetectingResolutionContext resolutionContext) { if (!CastleDynamicProxyGenerator.CanGenerateProxy(typeOfFake, out string?reasonCannotGenerate)) { return(CreationResult.FailedToCreateFake(typeOfFake, reasonCannotGenerate)); } if (proxyOptions.ArgumentsForConstructor is not null) { var proxyGeneratorResult = this.GenerateProxy(typeOfFake, proxyOptions, proxyOptions.ArgumentsForConstructor); return(proxyGeneratorResult.ProxyWasSuccessfullyGenerated ? CreationResult.SuccessfullyCreated(proxyGeneratorResult.GeneratedProxy) : CreationResult.FailedToCreateFake(typeOfFake, proxyGeneratorResult.ReasonForFailure !)); } return(this.TryCreateFakeWithDummyArgumentsForConstructor( typeOfFake, proxyOptions, resolver, resolutionContext)); }
public override CreationResult TryCreateDummyValue(Type typeOfDummy, IDummyValueResolver resolver) { var success = this.DummyFactory.TryCreateDummyObject(typeOfDummy, out object result); return(success ? CreationResult.SuccessfullyCreated(result) : CreationResult.FailedToCreateDummy(typeOfDummy, "No Dummy Factory produced a result.")); }
public override CreationResult TryCreateDummyValue(DummyCreationSession session, Type typeOfDummy) { if (typeof(Delegate).IsAssignableFrom(typeOfDummy)) { return(CreationResult.FailedToCreateDummy(typeOfDummy, "It is a Delegate.")); } if (typeOfDummy.GetTypeInfo().IsAbstract) { return(CreationResult.FailedToCreateDummy(typeOfDummy, "It is abstract.")); } // Save the constructors as we try them. Avoids eager evaluation and double evaluation // of constructors enumerable. var consideredConstructors = new List <ResolvedConstructor>(); if (this.cachedConstructors.TryGetValue(typeOfDummy, out ConstructorInfo cachedConstructor)) { var resolvedConstructor = new ResolvedConstructor( cachedConstructor.GetParameters().Select(pi => pi.ParameterType), session, this.Resolver); if (resolvedConstructor.WasSuccessfullyResolved) { if (TryCreateDummyValueUsingConstructor(cachedConstructor, resolvedConstructor, out object result)) { return(CreationResult.SuccessfullyCreated(result)); } consideredConstructors.Add(resolvedConstructor); } } else { foreach (var constructor in GetConstructorsInOrder(typeOfDummy)) { var resolvedConstructor = new ResolvedConstructor( constructor.GetParameters().Select(pi => pi.ParameterType), session, this.Resolver); if (resolvedConstructor.WasSuccessfullyResolved && TryCreateDummyValueUsingConstructor(constructor, resolvedConstructor, out object result)) { this.cachedConstructors[typeOfDummy] = constructor; return(CreationResult.SuccessfullyCreated(result)); } consideredConstructors.Add(resolvedConstructor); } } if (consideredConstructors.Any()) { return(CreationResult.FailedToCreateDummy(typeOfDummy, consideredConstructors)); } return(CreationResult.FailedToCreateDummy(typeOfDummy, "It has no public constructors.")); }
public override CreationResult TryCreateDummyValue(Type typeOfDummy, IDummyValueResolver resolver) { if (typeOfDummy.GetTypeInfo().IsValueType&& typeOfDummy != typeof(void)) { return(CreationResult.SuccessfullyCreated(Activator.CreateInstance(typeOfDummy))); } return(CreationResult.FailedToCreateDummy(typeOfDummy, "It is not a value type.")); }
public override CreationResult TryCreateDummyValue( Type typeOfDummy, IDummyValueResolver resolver, LoopDetectingResolutionContext resolutionContext) { if (typeOfDummy.GetTypeInfo().IsGenericType&& typeOfDummy.GetGenericTypeDefinition() == typeof(Lazy <>)) { var typeOfLazyResult = typeOfDummy.GetGenericArguments()[0]; var method = CreateLazyDummyGenericDefinition.MakeGenericMethod(typeOfLazyResult); var dummy = method.Invoke(null, new object[] { resolver }); return(CreationResult.SuccessfullyCreated(dummy)); } return(CreationResult.FailedToCreateDummy(typeOfDummy, "It is not a Lazy.")); }
public CreationResult TryResolveDummyValue(DummyCreationSession session, Type typeOfDummy) { if (!session.TryBeginToResolveType(typeOfDummy)) { return(CreationResult.FailedToCreateDummy(typeOfDummy, "Recursive dependency detected. Already resolving " + typeOfDummy + '.')); } var creationResult = this.TryResolveDummyValueWithAllAvailableStrategies(session, typeOfDummy); if (creationResult.WasSuccessful) { session.OnSuccessfulResolve(typeOfDummy); } return(creationResult); }
public override CreationResult MergeIntoDummyResult(CreationResult other) { Guard.AgainstNull(other, "other"); if (other.WasSuccessful) { return(other); } var failedOther = (FailedCreationResult)other; return(new FailedCreationResult( this.type, CreationMode.Dummy, MergeReasonsForFailure(this.reasonsForFailure, failedOther.reasonsForFailure), MergeConsideredConstructors(this.consideredConstructors, failedOther.consideredConstructors))); }
public CreationResult CreateFakeInterface(Type typeOfFake, IProxyOptions proxyOptions) { if (proxyOptions.ArgumentsForConstructor is not null) { throw new ArgumentException(DynamicProxyMessages.ArgumentsForConstructorOnInterfaceType); } var fakeCallProcessorProvider = this.fakeCallProcessorProviderFactory(typeOfFake, proxyOptions); var proxyGeneratorResult = CastleDynamicProxyGenerator.GenerateInterfaceProxy( typeOfFake, proxyOptions.AdditionalInterfacesToImplement, proxyOptions.Attributes, fakeCallProcessorProvider); return(proxyGeneratorResult.ProxyWasSuccessfullyGenerated ? CreationResult.SuccessfullyCreated(proxyGeneratorResult.GeneratedProxy) : CreationResult.FailedToCreateFake(typeOfFake, proxyGeneratorResult.ReasonForFailure !)); }
public override CreationResult TryCreateDummyValue( Type typeOfDummy, IDummyValueResolver resolver, LoopDetectingResolutionContext resolutionContext) { if (typeOfDummy == typeof(Task)) { return(CreationResult.SuccessfullyCreated(TaskHelper.CompletedTask)); } if (typeOfDummy.IsGenericType && typeOfDummy.GetGenericTypeDefinition() == typeof(Task <>)) { var typeOfTaskResult = typeOfDummy.GetGenericArguments()[0]; var creationResult = resolver.TryResolveDummyValue(typeOfTaskResult, resolutionContext); object?taskResult = creationResult.WasSuccessful ? creationResult.Result : typeOfTaskResult.GetDefaultValue(); var method = GenericFromResultMethodDefinition.MakeGenericMethod(typeOfTaskResult); return(CreationResult.SuccessfullyCreated(method.Invoke(null, new[] { taskResult }))); } if (typeOfDummy.FullName == "System.Threading.Tasks.ValueTask") { return(CreationResult.SuccessfullyCreated(typeOfDummy.GetDefaultValue())); } if (typeOfDummy.IsGenericType && !typeOfDummy.IsGenericTypeDefinition && typeOfDummy.FullName is string fullName && fullName.StartsWith("System.Threading.Tasks.ValueTask`", StringComparison.Ordinal)) { var typeOfTaskResult = typeOfDummy.GetGenericArguments()[0]; var creationResult = resolver.TryResolveDummyValue(typeOfTaskResult, resolutionContext); object?taskResult = creationResult.WasSuccessful ? creationResult.Result : typeOfTaskResult.GetDefaultValue(); var ctor = typeOfDummy.GetConstructor(new[] { typeOfTaskResult }) !; return(CreationResult.SuccessfullyCreated(ctor.Invoke(new[] { taskResult }))); } return(CreationResult.FailedToCreateDummy(typeOfDummy, "It is not a Task.")); }
public CreationResult TryResolveDummyValueWithAllAvailableStrategies(Type typeOfDummy) { CreationResult creationResult = null; foreach (var strategy in this.strategies) { var thisCreationResult = strategy.TryCreateDummyValue(typeOfDummy, this); if (thisCreationResult.WasSuccessful) { this.strategyCache.TryAdd(typeOfDummy, strategy); return(thisCreationResult); } creationResult = CreationResult.MergeIntoDummyResult(creationResult, thisCreationResult); } this.strategyCache.TryAdd(typeOfDummy, new UnableToResolveStrategy(creationResult)); return(creationResult); }
/// <summary> /// Returns a creation result for a dummy by combining two results. /// Successful results are preferred to failed. Failed results will have their reasons for failure aggregated. /// </summary> /// <param name="one">One result to merge. May be <code>null</code>.</param> /// <param name="other">The other result to merge. Must not be <code>null</code>.</param> /// <returns>A combined creation result. Successful if either input was successful, and failed otherwise.</returns> public static CreationResult MergeIntoDummyResult(CreationResult one, CreationResult other) { Guard.AgainstNull(other, "other"); if (one == null || other.WasSuccessful) { return(other.AsDummyResult()); } if (one.WasSuccessful) { return(one.AsDummyResult()); } return(new CreationResult( one.type, CreationMode.Dummy, MergeReasonsForFailure(one.reasonsForFailure, other.reasonsForFailure), MergeConsideredConstructors(one.consideredConstructors, other.consideredConstructors))); }
public override CreationResult TryCreateDummyValue(Type typeOfDummy, IDummyValueResolver resolver) { if (typeOfDummy.GetTypeInfo().IsGenericType&& typeOfDummy.GetGenericTypeDefinition() == typeof(Lazy <>)) { var typeOfLazyResult = typeOfDummy.GetGenericArguments()[0]; var creationResult = resolver.TryResolveDummyValue(typeOfLazyResult); object lazyResult = creationResult.WasSuccessful ? creationResult.Result : typeOfLazyResult.GetDefaultValue(); var funcType = typeof(Func <>).MakeGenericType(typeOfLazyResult); var method = CreateGenericFromResultMethodDefinition().MakeGenericMethod(typeOfLazyResult); var func = method.Invoke(null, new[] { lazyResult }); var dummy = typeOfDummy.GetConstructor(new[] { funcType, typeof(bool) }).Invoke(new[] { func, true }); return(CreationResult.SuccessfullyCreated(dummy)); } return(CreationResult.FailedToCreateDummy(typeOfDummy, "It is not a Lazy.")); }
public override CreationResult TryCreateDummyValue(Type typeOfDummy, IDummyValueResolver resolver) { if (typeOfDummy == typeof(Task)) { return(CreationResult.SuccessfullyCreated(TaskHelper.FromResult(default(object)))); } if (typeOfDummy.GetTypeInfo().IsGenericType&& typeOfDummy.GetGenericTypeDefinition() == typeof(Task <>)) { var typeOfTaskResult = typeOfDummy.GetGenericArguments()[0]; var creationResult = resolver.TryResolveDummyValue(typeOfTaskResult); object taskResult = creationResult.WasSuccessful ? creationResult.Result : typeOfTaskResult.GetDefaultValue(); var method = GenericFromResultMethodDefinition.MakeGenericMethod(typeOfTaskResult); return(CreationResult.SuccessfullyCreated(method.Invoke(null, new[] { taskResult }))); } return(CreationResult.FailedToCreateDummy(typeOfDummy, "It is not a Task.")); }
private CreationResult TryResolveDummyValueWithAllAvailableStrategies( Type typeOfDummy, LoopDetectingResolutionContext resolutionContext) { CreationResult creationResult = CreationResult.Untried; foreach (var strategy in this.strategies) { var thisCreationResult = strategy.TryCreateDummyValue(typeOfDummy, this, resolutionContext); if (thisCreationResult.WasSuccessful) { this.strategyCache.TryAdd(typeOfDummy, strategy); return(thisCreationResult); } creationResult = creationResult.MergeIntoDummyResult(thisCreationResult); } this.strategyCache.TryAdd(typeOfDummy, new UnableToResolveStrategy(creationResult)); return(creationResult); }
public CreationResult TryResolveDummyValue(Type typeOfDummy, LoopDetectingResolutionContext resolutionContext) { if (this.strategyCache.TryGetValue(typeOfDummy, out ResolveStrategy cachedStrategy)) { return(cachedStrategy.TryCreateDummyValue(typeOfDummy, this, resolutionContext)); } if (!resolutionContext.TryBeginToResolve(typeOfDummy)) { return(CreationResult.FailedToCreateDummy(typeOfDummy, "Recursive dependency detected. Already resolving " + typeOfDummy + '.')); } var creationResult = this.TryResolveDummyValueWithAllAvailableStrategies(typeOfDummy, resolutionContext); if (creationResult.WasSuccessful) { resolutionContext.OnSuccessfulResolve(typeOfDummy); } return(creationResult); }
public override CreationResult TryCreateDummyValue(Type typeOfDummy, IDummyValueResolver resolver, LoopDetectingResolutionContext resolutionContext) { if (IsTuple(typeOfDummy)) { var argTypes = typeOfDummy.GetTypeInfo().GetGenericArguments(); var args = new object[argTypes.Length]; for (int i = 0; i < argTypes.Length; i++) { var argType = argTypes[i]; var creationResult = resolver.TryResolveDummyValue(argType, resolutionContext); args[i] = creationResult.WasSuccessful ? creationResult.Result : argType.GetDefaultValue(); } var dummy = Activator.CreateInstance(typeOfDummy, args); return(CreationResult.SuccessfullyCreated(dummy)); } return(CreationResult.FailedToCreateDummy(typeOfDummy, "It is not a tuple.")); }
public CreationResult CreateFake(Type typeOfFake, IProxyOptions proxyOptions, DummyCreationSession session, IDummyValueResolver resolver) { if (proxyOptions.Attributes.Any()) { return(CreationResult.FailedToCreateFake(typeOfFake, "Faked delegates cannot have custom attributes applied to them.")); } if (proxyOptions.ArgumentsForConstructor != null && proxyOptions.ArgumentsForConstructor.Any()) { return(CreationResult.FailedToCreateFake(typeOfFake, "Faked delegates cannot be made using explicit constructor arguments.")); } if (proxyOptions.AdditionalInterfacesToImplement.Any()) { return(CreationResult.FailedToCreateFake(typeOfFake, "Faked delegates cannot be made to implement additional interfaces.")); } var fakeCallProcessorProvider = this.fakeCallProcessorProviderFactory(typeOfFake, proxyOptions); var proxyGeneratorResult = DelegateProxyGenerator.GenerateProxy(typeOfFake, fakeCallProcessorProvider); return(proxyGeneratorResult.ProxyWasSuccessfullyGenerated ? CreationResult.SuccessfullyCreated(proxyGeneratorResult.GeneratedProxy) : CreationResult.FailedToCreateFake(typeOfFake, proxyGeneratorResult.ReasonForFailure)); }
private CreationResult TryResolveDummyValueWithAllAvailableStrategies(DummyCreationSession session, Type typeOfDummy) { if (this.strategyCache.TryGetValue(typeOfDummy, out ResolveStrategy cachedStrategy)) { return(cachedStrategy.TryCreateDummyValue(session, typeOfDummy)); } CreationResult creationResult = null; foreach (var strategy in this.strategies) { var thisCreationResult = strategy.TryCreateDummyValue(session, typeOfDummy); if (thisCreationResult.WasSuccessful) { this.strategyCache.TryAdd(typeOfDummy, strategy); return(thisCreationResult); } creationResult = CreationResult.MergeIntoDummyResult(creationResult, thisCreationResult); } this.strategyCache.TryAdd(typeOfDummy, new UnableToResolveStrategy(creationResult)); return(creationResult); }
public CreationResult CreateFake( Type typeOfFake, IProxyOptions proxyOptions, IDummyValueResolver resolver, LoopDetectingResolutionContext resolutionContext) { if (!resolutionContext.TryBeginToResolve(typeOfFake)) { return(CreationResult.FailedToCreateFake(typeOfFake, "Recursive dependency detected. Already resolving " + typeOfFake + '.')); } var result = this.CreateFakeWithoutLoopDetection( typeOfFake, proxyOptions, resolver, resolutionContext); if (result.WasSuccessful) { resolutionContext.OnSuccessfulResolve(typeOfFake); } return(result); }
public CreationResult CreateFake( Type typeOfFake, IProxyOptions proxyOptions, IDummyValueResolver resolver, LoopDetectingResolutionContext resolutionContext) { if (!resolutionContext.TryBeginToResolve(typeOfFake)) { return(CreationResult.FailedToCreateFake(typeOfFake, "Recursive dependency detected. Already resolving " + typeOfFake + '.')); } try { return(this.CreateFakeWithoutLoopDetection( typeOfFake, proxyOptions, resolver, resolutionContext)); } finally { resolutionContext.EndResolve(typeOfFake); } }
public override CreationResult MergeIntoDummyResult(CreationResult other) => this;
/// <summary> /// Returns a creation result for a dummy by combining two results. /// Successful results are preferred to failed. Failed results will have their reasons for failure aggregated. /// </summary> /// <param name="other">The other result to merge. Must not be <c>null</c>.</param> /// <returns>A combined creation result. Successful if either input was successful, and failed otherwise.</returns> public abstract CreationResult MergeIntoDummyResult(CreationResult other);
public UnableToResolveStrategy(CreationResult creationResult) { this.creationResult = creationResult; }