Adding new dynamic properties - c#-4.0

we read in msdn we "Adding new dynamic properties" by using DynamicObject Class
i write a following program
public class DemoDynamicObject : DynamicObject
{
}
class Program
{
public static void Main()
{
dynamic dd = new DemoDynamicObject();
dd.FirstName = "abc";
}
}
But when i run this program it gives runtime error :'DemoDynamicObject' does not contain a definition for 'FirstName'
if we adding dynamic property by using DynamicObject Class then why it can give this error
can anyone tell me reason and solution?

When using DynamicObject as your base class, you should provide specific overrides to TryGetMember and TrySetMember to keep track of the dynamic properties you are creating (based on the DynamicObject MSDN documentation):
class DemoDynamicObject: DynamicObject
{
Dictionary<string, object> dictionary
= new Dictionary<string, object>();
public override bool TryGetMember(
GetMemberBinder binder, out object result)
{
string name = binder.Name;
return dictionary.TryGetValue(name, out result);
}
public override bool TrySetMember(
SetMemberBinder binder, object value)
{
dictionary[binder.Name] = value;
return true;
}
}
If you just want to have a dynamic object that you can add properties to, you can simply use an ExpandoObject instance, and skip the custom class inheriting from DynamicObject.

Related

Map object properties to dictionary on automapper

I am trying to map an object to a dictionary in a way that each property will be a dictionary item.
Object with id and name -> dictionary with two items containing property name and value.
I know it is a simple thing, but I was not able to find a solution for it. Maybe it is something I am not understanding...
I receive the following error:
Unmapped members were found. Review the types and members below.
Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters
=======================================================================================================================================================================================================================================================================
Book -> Dictionary`2 (Destination member list)
Book -> System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]] (Destination member list)
Unmapped properties:
Keys
Values
Item
In the following code you can see my implementation:
using AutoMapper;
var book = new Book()
{
Id = 1,
Name = "A"
};
IMapper mapper = new Mapper(new MapperConfiguration(
config => config.CreateMap<Book, Dictionary<string, string>>()
.ConstructUsing((source, dest) => new Dictionary<string, string>()
{
{ "id", source.Id.ToString() },
{"name", source.Name}
})));
mapper.ConfigurationProvider.AssertConfigurationIsValid();
var bookData = new Dictionary<string, string>();
mapper.Map(book, bookData);
public class Book
{
public int Id { get; set; }
public string Name { get; set; }
}
As #Lucian mentioned in a comment, Automapper has built-in methods to convert object from/to dynamic, Dictionary<string, object>.
However, I think that there is an issue if you implement a converter to Dictionary<string, string>.
Hence, it is better to build a custom implementation for the conversion as below:
using System.Reflection;
using Newtonsoft.Json;
public static class DictionaryExtensions
{
public static Dictionary<string, string> ToDictionary<T>(this T src) where T : new()
{
Dictionary<string, string> result = new ();
PropertyInfo[] properties = typeof(T).GetProperties();
foreach (PropertyInfo prop in properties)
{
result.Add(prop.Name, prop.PropertyType == typeof(string)
? prop.GetValue(src)?.ToString()
: JsonConvert.SerializeObject(prop.GetValue(src)));
}
return result;
}
}
For caller:
var bookData = book.ToDictionary();
Demo # .NET Fiddle

Forgetting to map classes with AutoMapper

The application I'm working on has several places where we use AutoMapper to map entities.
The problem is if I had a model entity from one side to the other of the project, many times I forget to add the mapping for the new entity (I just need a copy paste from other entities), ending up that the solution compiles and I get no exception.
It just launches the application without full functionality and no debugging messages, which makes difficult to figure out what I've missed.
Is there any way to force the compiler at compile time to give me an error in case I forget to do a mapping?
AFAIK, there isn't a possibility to force compile-time checking for Automapper.
Nevertheless, there is a possibility to verify the correctness of your mappings:
After you've defined all your mappings, call the AssertConfigurationIsValid method which will throws an AutoMapperConfigurationException exception if the defined mappings are broken.
You can make this a part of your unit or integration test suite.
I had the same problem and decided to solve it by wrapping up AutoMapper. For each source-destination map I provide a method that I create after I've added it to my AutoMapper profile.
This may take away some of the ease of implementing AutoMapper but I find the compile time checking worth it.
public class MyType {
public string SomeProperty { get;set; }
}
public class MyOtherType {
public string SomeProperty { get;set; }
}
public class MyAlternateType {
public string AlternateProperty {get;set;}
}
public class AutoMapperProfile : Profile {
public AutoMapperProfile() {
CreateMap<MyType, MyOtherType>();
CreateMap<MyAlternateType, MyOtherType>()
.ForMember(ot => ot.SomeProperty, options => options.MapFrom(at => at.AlternateProperty));
}
}
public interface IMyMappingProvider {
// Uncomment below for Queryable Extensions
//IQueryable<TDestination> ProjectTo<TSource, TDestination>(IQueryable<TSource> source, params Expression<Func<TDestination, object>>[] membersToExpand);
//IQueryable<TDestination> ProjectTo<TSource, TDestination>(IQueryable<TSource> source, IDictionary<string, object> parameters, params string[] membersToExpand);
/*
* Add your mapping declarations below
*/
MyOtherType MapToMyOtherType(MyType source);
MyOtherType MapToMyOtherType(MyAlternateType source);
}
public class MyMappingProvider : IMyMappingProvider {
private IMapper Mapper { get; set; }
public MyMappingProvider(IMapper mapper) {
Mapper = mapper;
}
/* Uncomment this for Queryable Extensions
public IQueryable<TDestination> ProjectTo<TSource, TDestination>(IQueryable<TSource> source, params Expression<Func<TDestination, object>>[] membersToExpand) {
return new ProjectionExpression(source, Mapper.ConfigurationProvider.ExpressionBuilder).To<TDestination>(null, membersToExpand);
}
public IQueryable<TDestination> ProjectTo<TSource, TDestination>(IQueryable<TSource> source, IDictionary<string, object> parameters, params string[] membersToExpand) {
return new ProjectionExpression(source, Mapper.ConfigurationProvider.ExpressionBuilder).To<TDestination>(parameters, membersToExpand);
}
*/
/*
* Implement your mapping methods below
*/
public MyOtherType MapToMyOtherType(MyType source) {
return Mapper.Map<MyType, MyOtherType>(source);
}
public MyOtherType MapToMyOtherType(MyAlternateType source) {
return Mapper.Map<MyAlternateType, MyOtherType>(source);
}
}
If you are using the AutoMapper's Queryable extensions you can add the following class and uncomment the Queryable Extensions code above.
public static class QueryableExtensions {
/*
* Implement your extension methods below
*/
public static IQueryable<MyOtherType> ProjectToMyOtherType(this IQueryable<MyType> source, IMyMappingProvider mapper, params Expression<Func<MyOtherType, object>>[] membersToExpand)
{
return mapper.ProjectTo<MyType, MyOtherType>(source, membersToExpand);
}
public static IQueryable<MyOtherType> ProjectToMyOtherType(this IQueryable<MyAlternateType> source, IMyMappingProvider mapper, params Expression<Func<MyOtherType, object>>[] membersToExpand)
{
return mapper.ProjectTo<MyAlternateType, MyOtherType>(source, membersToExpand);
}
}
Tested with AutoMapper 6.1.1 using LinqPad:
var autoMapperConfig = new MapperConfiguration(cfg => { cfg.AddProfile(new AutoMapperProfile()); });
IMyMappingProvider mapper = new MyMappingProvider(autoMapperConfig.CreateMapper());
var myTypes = new List<MyType>()
{
new MyType() {SomeProperty = "Test1"},
new MyType() {SomeProperty = "Test2"},
new MyType() {SomeProperty = "Test3"}
};
myTypes.AsQueryable().ProjectToMyOtherType(mapper).Dump();
var myAlternateTypes = new List<MyAlternateType>()
{
new MyAlternateType() {AlternateProperty = "AlternateTest1"},
new MyAlternateType() {AlternateProperty = "AlternateTest2"},
new MyAlternateType() {AlternateProperty = "AlternateTest3"}
};
myAlternateTypes.AsQueryable().ProjectToMyOtherType(mapper).Dump();
mapper.MapToMyOtherType(myTypes[0]).Dump();
As #serge.karalenka said, don't forget to still test your mapping configuration by calling AssertConfigurationIsValid().

Using DynamicObject (IDynamicMetaObjectProvider) as a component of a static type leads to infinite loop

I'm trying to create a dynamic object that can be used as a component of a static object. Here is a contrived example of what I'm trying to accomplish.
Here is the dynamic component:
public class DynamicComponent : DynamicObject
{
public override bool TryInvokeMember(
InvokeMemberBinder binder,
object[] args,
out object result)
{
result = "hello";
return true;
}
}
And here is a class where inheriting from DynamicObject isn't an option...assume that there is some third party class that I'm forced to inherit from.
public class AStaticComponent : VendorLibraryClass, IDynamicMetaObjectProvider
{
IDynamicMetaObjectProvider component = new DynamicComponent();
public DynamicMetaObject GetMetaObject(Expression parameter)
{
var result = component.GetMetaObject(parameter);
return result;
}
}
The direct usage of DynamicComponent works:
dynamic dynamicComponent = new DynamicComponent();
Assert.AreEqual(dynamicComponent.AMethod(), "hello");
However, forwarding the GetMetaObject through AStaticComponent causes some form of an infinite loop.
dynamic dynamicComponent = new AStaticComponent();
Assert.AreEqual(dynamicComponent.AMethod(), "hello"); //causes an infinite loop
Anyone know why this occurs?
And if it's some baked in behavior of DynamicObject that I cannot change, could someone provide some help on how to create a IDynamicMetaObjectProvider from scratch to accomplish a component based dynamic object (just something to get things started)?
I think the problem is that the Expression parameter passed to GetMetaObject represents the target of the dynamic invocation (i.e. the current object). You are passing the outer object to the call on component.GetMetaObject, so the returned meta object is trying to resolve the call to AMethod on the outer object instead of itself, hence the infinite loop.
You can create your own meta object which delegates to the inner component when binding member invocations:
public class AStaticComponent : VendorLibraryClass, IDynamicMetaObjectProvider
{
IDynamicMetaObjectProvider component = new DynamicComponent();
public DynamicMetaObject GetMetaObject(Expression parameter)
{
return new DelegatingMetaObject(component, parameter, BindingRestrictions.GetTypeRestriction(parameter, this.GetType()), this);
}
private class DelegatingMetaObject : DynamicMetaObject
{
private readonly IDynamicMetaObjectProvider innerProvider;
public DelegatingMetaObject(IDynamicMetaObjectProvider innerProvider, Expression expr, BindingRestrictions restrictions)
: base(expr, restrictions)
{
this.innerProvider = innerProvider;
}
public DelegatingMetaObject(IDynamicMetaObjectProvider innerProvider, Expression expr, BindingRestrictions restrictions, object value)
: base(expr, restrictions, value)
{
this.innerProvider = innerProvider;
}
public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
{
var innerMetaObject = innerProvider.GetMetaObject(Expression.Constant(innerProvider));
return innerMetaObject.BindInvokeMember(binder, args);
}
}
}
#Lee's answer is really useful, I wouldn't have known where to get started without it. But from using it in production code, I believe it has a subtle bug.
Dynamic calls are cached at the call site, and Lee's code produces a DynamicMetaObject which effectively states that the inner handling object is a constant. If you have a place in your code where you call a dynamic method on an instance of AStaticObject, and later the same point in the code calls the same method on a different instance of AStaticObject (i.e. because the variable of type AStaticObject now has a different value) then the code will make the wrong call, always calling methods on the handling object from the first instance encountered at that place in the code during that run of the code.
This is a like-for-like replacement, the key difference being the use of Expression.Field to tell the dynamic call caching system that the handling object depends on the parent object:
public class AStaticComponent : VendorLibraryClass, IDynamicMetaObjectProvider
{
IDynamicMetaObjectProvider component = new DynamicComponent();
public DynamicMetaObject GetMetaObject(Expression parameter)
{
return new DelegatingMetaObject(parameter, this, nameof(component));
}
private class DelegatingMetaObject : DynamicMetaObject
{
private readonly DynamicMetaObject innerMetaObject;
public DelegatingMetaObject(Expression expression, object outerObject, string innerFieldName)
: base(expression, BindingRestrictions.Empty, outerObject)
{
FieldInfo innerField = outerObject.GetType().GetField(innerFieldName, BindingFlags.Instance | BindingFlags.NonPublic);
var innerObject = innerField.GetValue(outerObject);
var innerDynamicProvider = innerObject as IDynamicMetaObjectProvider;
innerMetaObject = innerDynamicProvider.GetMetaObject(Expression.Field(Expression.Convert(Expression, LimitType), innerField));
}
public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
{
return binder.FallbackInvokeMember(this, args, innerMetaObject.BindInvokeMember(binder, args));
}
}
}

How can I specify which instances of a class are unmarshalled using an XMLAdapter?

I have the following java class and have placed an XmlJavaAdapter annotation on the payerPartyReference variable. I want the adapter PartyReferenceAdapter to be used for unmarshalling ONLY this variable, not any other variables which have the same type of PartyReference, whether in this class or some other class. How can I do this? Thanks for your help!
public class InitialPayment extends PaymentBase
{
// Want PartyReferenceAdapter to be used here
#XmlJavaTypeAdapter(PartyReferenceAdapter.class)
protected PartyReference payerPartyReference;
//
// Dont want PartyReferenceAdapter to be used here
protected PartyReference receiverPartyReference;
//
protected AccountReference receiverAccountReference;
#XmlSchemaType(name = "date")
protected XMLGregorianCalendar adjustablePaymentDate;
#XmlSchemaType(name = "date")
protected XMLGregorianCalendar adjustedPaymentDate;
protected Money paymentAmount;
}
My Adapter is defined as follows:
public class PartyReferenceAdapter
extends XmlAdapter < Object, PartyReference > {
public PartyReference unmarshal(Object obj) throws Exception {
Element element = null;
if (obj instanceof Element) {
element = (Element)obj;
String reference_id = element.getAttribute("href");
PartyReference pr = new PartyReference();
pr.setHref(reference_id);
return pr;
}
public Object marshal(PartyReference arg0) throws Exception {
return null;
}
}
Field/Property Level
If you set #XmlJavaTypeAdapter on a field/property it will only be used for that property.
http://bdoughan.blogspot.com/2010/07/xmladapter-jaxbs-secret-weapon.html
Type Level
If you set #XmlJavaTypeAdapter on a type, then it will used for all references to that type.
http://bdoughan.blogspot.com/2010/12/jaxb-and-immutable-objects.html
Package Level
If you set #XmlJavaTypeAdapter on a package, then it will be used for all references to that type within that package:
http://bdoughan.blogspot.com/2011/05/jaxb-and-joda-time-dates-and-times.html

how to avoid change of class on assigning derived class object to base class object in c# 4?

Hello from C# and OOP newbie.
How can I avoid change of class on assigning derived class object to base class object in c#?
After i run code bellow i get this response
obj1 is TestingField.Two
obj2 is TestingField.Two
I expected that i will lose access to derived methods and properties (which I did) after assigning reference but I did not expect change of class in midcode :S
using System;
namespace TestingField
{
class Program
{
static void Main(string[] args)
{
One obj1 = new One();
Two obj2 = new Two();
obj1 = obj2;
Console.WriteLine("obj1 is {0}", obj1.GetType());
Console.WriteLine("obj2 is {0}", obj2.GetType());
Console.ReadLine();
}
}
class One
{
}
class Two : One
{
public void DoSomething()
{
Console.WriteLine("Did Something.");
}
}
}
While you are right, you will lose access to members declared in the derived type, the object won't suddenly change it's type or implementation. You can access only members declared on the base type, but the implementation of the derived type is used in the case of overriden members, which is the case with GetType, which is a compiler generated method which automatically overrides the base class's implementation.
Extending your example:
class One
{
public virtual void SayHello()
{
Console.WriteLine("Hello from Base");
}
}
class Two : One
{
public void DoSomething()
{
Console.WriteLine("Did Something.");
}
public override void SayHello()
{
Console.WriteLine("Hello from Derived");
}
}
Given:
One obj = new Two();
obj.SayHello(); // will return "Hello from Derived"
GetType is a virtual method gives you the dynamic type of the object.
I think you want the static type of the variable. You can't get this by calling a method on the object referenced by the variable. Instead just write typeof(TypeName), which is typeof(One) or typeof(Two) in your case.
Alternatively in your subclass you can use a new method which hides the original one instead of overriding it:
class One
{
public string MyGetType() { return "One"; }
}
class Two : One
{
public new string MyGetType() { return "Two"; }
}
class Program
{
private void Run()
{
One obj1 = new One();
Two obj2 = new Two();
obj1 = obj2;
Console.WriteLine("obj1.GetType(): " + obj1.GetType());
Console.WriteLine("obj2.GetType(): " + obj2.GetType());
Console.WriteLine("obj1.MyGetType(): " + obj1.MyGetType());
Console.WriteLine("obj2.MyGetType(): " + obj2.MyGetType());
}
}
Result:
obj1.GetType(): Two
obj2.GetType(): Two
obj1.MyGetType(): One
obj2.MyGetType(): Two
You haven't "changed class". The type of the variable obj1 is still One. You have assigned an instance of Two to this variable, which is allowed since Two inherits from One. The GetType method gives you the actual type of the object currently referenced by this variable, not the type of the declared variable itself.

Resources