Skip to content

Commit

Permalink
Adds support to mix code between abstract classes and instance classe…
Browse files Browse the repository at this point in the history
…s using the proxy
  • Loading branch information
tonyredondo committed Jun 23, 2020
1 parent 023037e commit debd47e
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 5 deletions.
4 changes: 2 additions & 2 deletions src/Wanhjor.ObjectInspector/DuckType.Create.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public static object Create(Type duckType, object instance)
var type = GetOrCreateProxyType(duckType, instance.GetType());

// Create instance
var objInstance = (ISettableDuckType)FormatterServices.GetUninitializedObject(type);
var objInstance = (ISettableDuckType)Activator.CreateInstance(type);
objInstance.SetInstance(instance);
return objInstance;
}
Expand All @@ -46,7 +46,7 @@ public static object Create(Type duckType, object instance)
public static object Create(Type duckType, Type instanceType)
{
var type = GetOrCreateProxyType(duckType, instanceType);
return FormatterServices.GetUninitializedObject(type);
return Activator.CreateInstance(type);
}
}
}
13 changes: 11 additions & 2 deletions src/Wanhjor.ObjectInspector/DuckType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ private static Type CreateProxyType(Type duckType, Type instanceType)
parentType, interfaceTypes);

// Define .ctor
typeBuilder.DefineDefaultConstructor(MethodAttributes.Private);
typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);

// Create instance field if is null
instanceField ??= CreateInstanceField(typeBuilder);
Expand Down Expand Up @@ -216,7 +216,9 @@ private static void CreateProperties(Type baseType, Type instanceType, FieldInfo
var selectedProperties = GetProperties(baseType);
foreach (var iProperty in selectedProperties)
{
var propertyBuilder = typeBuilder.DefineProperty(iProperty.Name, PropertyAttributes.None, iProperty.PropertyType, null);
PropertyBuilder? propertyBuilder = null;
if ((iProperty.CanRead && iProperty.GetMethod.IsAbstract) || (iProperty.CanWrite && iProperty.SetMethod.IsAbstract))
propertyBuilder = typeBuilder.DefineProperty(iProperty.Name, PropertyAttributes.None, iProperty.PropertyType, null);

var duckAttrs = new List<DuckAttribute>(iProperty.GetCustomAttributes<DuckAttribute>(true));
if (duckAttrs.Count == 0)
Expand All @@ -242,6 +244,8 @@ private static void CreateProperties(Type baseType, Type instanceType, FieldInfo
if (prop is null)
continue;

propertyBuilder ??= typeBuilder.DefineProperty(iProperty.Name, PropertyAttributes.None, iProperty.PropertyType, null);

if (iProperty.CanRead)
propertyBuilder.SetGetMethod(GetPropertyGetMethod(instanceType, typeBuilder, iProperty, prop, instanceField));

Expand All @@ -254,6 +258,8 @@ private static void CreateProperties(Type baseType, Type instanceType, FieldInfo
var field = instanceType.GetField(duckAttr.Name, duckAttr.Flags);
if (field is null)
continue;

propertyBuilder ??= typeBuilder.DefineProperty(iProperty.Name, PropertyAttributes.None, iProperty.PropertyType, null);

if (iProperty.CanRead)
propertyBuilder.SetGetMethod(GetFieldGetMethod(instanceType, typeBuilder, iProperty, field, instanceField));
Expand All @@ -267,6 +273,9 @@ private static void CreateProperties(Type baseType, Type instanceType, FieldInfo
break;
}

if (propertyBuilder is null)
continue;

if (iProperty.CanRead && propertyBuilder.GetMethod is null)
propertyBuilder.SetGetMethod(GetNotFoundGetMethod(instanceType, typeBuilder, iProperty));

Expand Down
2 changes: 1 addition & 1 deletion src/Wanhjor.ObjectInspector/Wanhjor.ObjectInspector.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<Description>An efficient .NET object inspector/accesor to avoid reflection usage with duck typing support.</Description>
<LangVersion>8</LangVersion>
<Nullable>enable</Nullable>
<Version>0.4.0-beta.2</Version>
<Version>0.4.0-beta.3</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Title>ObjectInspector</Title>
<Authors>Daniel Redondo</Authors>
Expand Down
51 changes: 51 additions & 0 deletions test/Wanhjor.ObjectInspector.Tests/DuckTypeAbstractTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,22 @@ public void FactoryRentTest()
lease.Instance["Changes"] = "Changed";
}
}

[Fact]
[MethodImpl(MethodImplOptions.NoOptimization)]
public void ReverseDuckTest()
{
var obj = new ReverseObject();

var duck = obj.DuckAs<ReverseDuck>();
obj.SetProxyObject(duck);

var values = duck.GetValues();
Assert.Equal("From Base => From Instance", values);

var name = duck.GetName();
Assert.Equal("From Base", name);
}
}

public abstract class AbstractDictio : DuckType
Expand All @@ -135,6 +151,41 @@ public abstract class AbstractDuckTestNoInherits
public abstract string Name { get; set; }
}

public abstract class ReverseDuck
{
public string Name { get; set; } = "From Base";

public abstract string Value { get; set; }

public string GetValues()
{
return $"{Name} => {Value}";
}

public abstract string GetName();
}

public interface IReverseExtractor
{
string Name { get; set; }
}

public class ReverseObject
{
private IReverseExtractor _extractor;
public string Value { get; set; } = "From Instance";

public string GetName()
{
return _extractor.Name;
}

public void SetProxyObject(object proxy)
{
_extractor = proxy.DuckAs<IReverseExtractor>();
}
}

public abstract class AbstractDuckTestObject : DuckType
{
public abstract string Name { get; set; }
Expand Down

0 comments on commit debd47e

Please sign in to comment.