Skip to content

Commit

Permalink
Fixes more CanBeCastTo() errors related to open generics types. Closes
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremydmiller committed Jan 27, 2015
1 parent 83f6131 commit 791a66c
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 15 deletions.
@@ -0,0 +1,21 @@
using System;
using NUnit.Framework;
using StructureMap.Pipeline;

namespace StructureMap.Testing.Bugs
{
[TestFixture]
public class Bug_300_naive_can_be_plugged_into_tests
{
public interface IInterface { }

[Test]
public void throw_defensive_check_on_constructor_instance()
{
Exception<ArgumentOutOfRangeException>.ShouldBeThrownBy(() =>
{
new ConstructorInstance(typeof (IInterface));
});
}
}
}
8 changes: 6 additions & 2 deletions src/StructureMap.Testing/ConcreteClassCreationTester.cs
Expand Up @@ -12,7 +12,10 @@ public class ConcreteClassCreationTester
[SetUp]
public void SetUp()
{
container = new Container(x => { x.For<IWidget>().Use(new ColorWidget("red")); });
container = new Container(_ =>
{
_.For<IWidget>().Use(new ColorWidget("red"));
});
}

#endregion
Expand All @@ -37,7 +40,8 @@ public IWidget Widget1
[Test]
public void can_create_a_concrete_class_by_default()
{
container.GetInstance<ConcreteClass>().Widget1.ShouldBeOfType<ColorWidget>();
container.GetInstance<ConcreteClass>()
.Widget1.ShouldBeOfType<ColorWidget>();
}

[Test]
Expand Down
Expand Up @@ -5,6 +5,7 @@
using StructureMap.Pipeline;
using StructureMap.Testing.Widget;
using StructureMap.Testing.Widget3;
using StructureMap.TypeRules;

namespace StructureMap.Testing.Configuration.DSL
{
Expand Down Expand Up @@ -34,6 +35,30 @@ public interface Something

public class OrangeSomething : SomethingElseEntirely
{
public readonly Guid Id = Guid.NewGuid();

public override string ToString()
{
return string.Format("OrangeSomething: {0}", Id);
}

protected bool Equals(OrangeSomething other)
{
return Id.Equals(other.Id);
}

public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((OrangeSomething) obj);
}

public override int GetHashCode()
{
return Id.GetHashCode();
}
}

public class RedSomething : Something
Expand Down Expand Up @@ -183,12 +208,22 @@ public void CreatePluginFamilyWithADefault()
container.GetInstance<IWidget>().ShouldBeOfType<ColorWidget>().Color.ShouldEqual("Red");
}

[Test]
public void weird_generics_casting()
{
typeof(SomethingElseEntirely).CanBeCastTo<SomethingElse>()
.ShouldBeTrue();
}

[Test]
public void CreatePluginFamilyWithReferenceToAnotherFamily()
{


var container = new Container(r =>
{
r.For<SomethingElseEntirely>().Use<OrangeSomething>();
// Had to be a singleton for this to work
r.ForSingletonOf<SomethingElseEntirely>().Use<OrangeSomething>();
r.For<SomethingElse>().Use(context =>
// If the return is cast to OrangeSomething, this works.
context.GetInstance<SomethingElseEntirely>());
Expand All @@ -199,9 +234,11 @@ public void CreatePluginFamilyWithReferenceToAnotherFamily()

var orangeSomething = container.GetInstance<SomethingElseEntirely>();
orangeSomething.ShouldBeOfType<OrangeSomething>();

container.GetInstance<SomethingElse>()
.ShouldBeOfType<OrangeSomething>()
.ShouldEqual(orangeSomething);

container.GetInstance<Something>()
.ShouldBeOfType<OrangeSomething>()
.ShouldEqual(orangeSomething);
Expand Down
1 change: 1 addition & 0 deletions src/StructureMap.Testing/StructureMap.Testing.csproj
Expand Up @@ -205,6 +205,7 @@
<Compile Include="Bugs\Bug_251_do_not_add_null_values_to_plugin_family_instance_cache.cs" />
<Compile Include="Bugs\Bug_255_InstanceAttribute_Implementation.cs" />
<Compile Include="Bugs\Bug_295_named_registrations_to_nested_container.cs" />
<Compile Include="Bugs\Bug_300_naive_can_be_plugged_into_tests.cs" />
<Compile Include="Bugs\Bug_313.cs" />
<Compile Include="Bugs\BuildUpBug.cs" />
<Compile Include="Bugs\closed_type_generic_is_in_get_all.cs" />
Expand Down
13 changes: 11 additions & 2 deletions src/StructureMap/Building/Interception/ParameterRewriter.cs
Expand Up @@ -13,7 +13,7 @@ public class ParameterRewriter : ExpressionVisitor
public static LambdaExpression ReplaceParameter(Type acceptsType, LambdaExpression expression,
ParameterExpression newParam)
{
var before = expression.Parameters.FirstOrDefault(x => { return x.Type.CanBeCastTo(acceptsType); });
var before = expression.Parameters.FirstOrDefault(x => x.Type == acceptsType) ?? expression.Parameters.FirstOrDefault(x => x.Type.CanBeCastTo(acceptsType));

if (before == null) return expression;

Expand All @@ -34,7 +34,16 @@ protected override Expression VisitParameter(ParameterExpression node)

if (_after.Type == _before.Type) return _after;

return Expression.Convert(_after, _before.Type);
try
{
return Expression.Convert(_after, _before.Type);
}
catch (Exception e)
{
throw e;
}
}


}
}
11 changes: 7 additions & 4 deletions src/StructureMap/Graph/GenericsPluginGraph.cs
Expand Up @@ -24,6 +24,8 @@ public static bool CanBeCast(Type pluginType, Type pluggedType)

private static bool checkGenericType(Type pluggedType, Type pluginType)
{
if (pluggedType == null || pluginType == null) return false;

if (pluginType.GetTypeInfo().IsAssignableFrom(pluggedType.GetTypeInfo())) return true;


Expand All @@ -41,17 +43,18 @@ private static bool checkGenericType(Type pluggedType, Type pluginType)
}
}

if (pluggedType.GetTypeInfo().BaseType.GetTypeInfo().IsGenericType)
var baseType = pluggedType.GetTypeInfo().BaseType;
if (baseType != null && baseType.GetTypeInfo().IsGenericType)
{
var baseType = pluggedType.GetTypeInfo().BaseType.GetGenericTypeDefinition();
var baseTypeGenericDefinition = baseType.GetGenericTypeDefinition();

if (baseType == pluginType)
if (baseTypeGenericDefinition == pluginType)
{
return true;
}
else
{
return CanBeCast(pluginType, baseType);
return CanBeCast(pluginType, baseTypeGenericDefinition);
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/StructureMap/Graph/PluginFamily.cs
Expand Up @@ -104,6 +104,8 @@ private void assertInstanceIsValidForThisPluginType(Instance instance)
{
if (instance.ReturnedType == typeof (object)) return;



if (instance.ReturnedType != null &&
!instance.ReturnedType.CanBeCastTo(_pluginType))
{
Expand All @@ -113,6 +115,8 @@ private void assertInstanceIsValidForThisPluginType(Instance instance)
}
}



public void SetDefault(Func<Instance> defaultInstance)
{
_defaultInstance = new Lazy<Instance>(defaultInstance);
Expand Down
5 changes: 5 additions & 0 deletions src/StructureMap/Pipeline/ConstructorInstance.cs
Expand Up @@ -39,6 +39,11 @@ public abstract class ConstructorInstance<TThis> : ExpressedInstance<TThis>, ICo

public ConstructorInstance(Type concreteType)
{
if (!concreteType.IsConcrete())
{
throw new ArgumentOutOfRangeException("concreteType","Only concrete types can be built by ConstructorInstance");
}

if (!concreteType.GetConstructors().Any())
{
throw new ArgumentOutOfRangeException(
Expand Down
3 changes: 1 addition & 2 deletions src/StructureMap/PipelineGraph.cs
Expand Up @@ -132,8 +132,7 @@ public void RegisterContainer(IContainer container)

public IPipelineGraph ToNestedGraph()
{
var nestedPluginGraph = new PluginGraph(Profile + " - Nested");
nestedPluginGraph.Parent = _pluginGraph;
var nestedPluginGraph = new PluginGraph(Profile + " - Nested") {Parent = _pluginGraph};

var instances = new ComplexInstanceGraph(this, nestedPluginGraph, ContainerRole.Nested);
return new PipelineGraph(nestedPluginGraph, instances, this, _singletons,
Expand Down
4 changes: 0 additions & 4 deletions src/StructureMap/TypeExtensions.cs
Expand Up @@ -181,10 +181,6 @@ public static bool CanBeCastTo(this Type pluggedType, Type pluginType)

if (pluggedType == pluginType) return true;

if (pluggedType.IsInterfaceOrAbstract())
{
return false;
}

if (pluginType.IsOpenGeneric())
{
Expand Down

0 comments on commit 791a66c

Please sign in to comment.