forked from reflection-emit/Cauldron
-
Notifications
You must be signed in to change notification settings - Fork 18
Anonymous Type to interface convertion
Alexei Stryker edited this page Jun 27, 2018
·
7 revisions
In some special cases (e.g. unit tests) it may be required to convert an anonymous type to a type that implements a certain interface. The CreateType(object) extension (Cauldron.Interception Fody addins) offers this functionality.
This also can be handy in situations where it is an overkill to create a new class.
Lazy programmers will love this.
To achieve this, a new type is weaved into your assembly.
private static void Main(string[] args)
{
var sample = new { Index = 0, Name = "Hello" }.CreateType<ISampleInterface>();
Console.WriteLine(sample.Name);
}
What gets compiled:
private static void Main(string[] args)
{
var sample = Assign(new
{
Index = 0,
Name = "Hello"
});
Console.WriteLine(sample.Name);
}
[EditorBrowsable(EditorBrowsableState.Never)]
private static SampleInterfaceCauldronAnonymousType Assign(AnonymousType<int, string> anonymousType)
{
return new SampleInterfaceCauldronAnonymousType
{
Index = anonymousType.Index,
Name = anonymousType.Name
};
}
The created type:
[EditorBrowsable(EditorBrowsableState.Never)]
[Serializable]
public sealed class SampleInterfaceCauldronAnonymousType : ISampleInterface
{
public int Index { get; set; }
public string Name { get; set; }
}
public IAddressData GetAddress(IUser user)
{
var data = Factory.Create<IDatabase>().GetAddress(user.UserId);
return new {
UserId = user.UserId,
Country = GetCountryName(data.CountryCode),
Street = $"{data.Street} {data.StreetNumber}",
ZipCode = data.ZipCode.ToString(),
Name = user.Fullname
}.CreateObject<IAddressData>();
}
The weaver will create a new public type that implements IAddressData and it will also add a new method to your class that assigns the value of the anonymous type to the public type.
private GeneratedTypeThatImplementsIAddressData Assign(TheAnonymousType anon)
{
return new GeneratedTypeThatImplementsIAddressData
{
UserId = anon.UserId,
Country = anon.Country,
Street = anon.Street,
ZipCode = anon.ZipCode,
Name = anon.Name
};
}
Your original implementation will be modified like the following:
public IAddressData GetAddress(IUser user)
{
var data = Factory.Create<IDatabase>().GetAddress(user.UserId);
return Assign(new {
UserId = user.UserId,
Country = GetCountryName(data.CountryCode),
Street = $"{data.Street} {data.StreetNumber}",
ZipCode = data.ZipCode.ToString(),
Name = user.Fullname
});
}