I have a dynamic object that looks as follows:
this.ChartDetails.Chart
'Chart' is dynamic. I want to see if a dynamic property exists on Chart named LeftYAxis. What is the best way to do this on dynamic objects?
I don't think this is a duplicate of How to detect if a property exists on an ExpandoObject? because it doesn't discuss the best method to do this for dynamic objects.
For a variety of reasons it's best to avoid try/catch blocks for control flow. Therefore, while Christopher's method attains the desired result, I find this preferable:
this.ChartDetails.Chart.GetType().GetProperty("LeftYAxis") != null;
bool isDefined = false;
object axis = null;
try
{
axis = this.ChartDetails.Chart.LeftYAxis;
isDefined = true;
}
catch(RuntimeBinderException)
{ }
This is what happens at runtime in the first place. (When you access a property the 'dynamic' piece of things only happens when a first-chance exception gets handled by the object's override of DynamicObject's TryGetMember and TrySetMember
Some objects (like ExpandoObject) are actually dictionaries under the hood and you can check them directly as follows:
bool isDefined = ((IDictionary<string, object>)this.ChartDetails.Chart)
.ContainsKey("LeftYAxis");
Basically: without knowing what actual type ChartDetails.Chart is (if it's an ExpandoObject a plain ol' subclass of object or a subclass of DynamicObject) there's no way besides the try/catch above. If you wrote the code for ChartDetails and Chart or have access to the source code you can determine what methods exist for the object and use those to check.
This Works if the dynamic object is a json/open-standard format.
I made two different method helpers one for open-standard format and one for "standard object".
// Checks if object typed json or xml has a specific property
public static bool IsPropertyExistsOpenStandardFormat(dynamic dynamicObject, string propertyName)
{
try
{
var x = dynamicObject[propertyName];
if (x != null)
return true;
}
catch
{
return false;
}
}
// Checks if standard object has a specific property
public static bool IsPropertyExistsStandard(dynamic dynamicObject, string propertyName)
{
return dynamicObject.GetType().GetProperty(propertyName) != null;
}
This one is working -:
public static bool IsPropertyExists(dynamic dynamicObj, string property)
{
try
{
var value=dynamicObj[property].Value;
return true;
}
catch (RuntimeBinderException)
{
return false;
}
}
Related
Using dynamic pattern perhaps? You can call any method/property using the dynamic keyword, right? How to check whether the method exist before calling myDynamicObject.DoStuff(), for example?
You could write something like that :
public static bool HasMethod(this object objectToCheck, string methodName)
{
var type = objectToCheck.GetType();
return type.GetMethod(methodName) != null;
}
Edit : you can even do an extension method and use it like this
myObject.HasMethod("SomeMethod");
via Reflection
var property = object.GetType().GetProperty("YourProperty")
property.SetValue(object,some_value,null);
Similar is for methods
It is an old question, but I just ran into it.
Type.GetMethod(string name) will throw an AmbiguousMatchException if there is more than one method with that name, so we better handle that case
public static bool HasMethod(this object objectToCheck, string methodName)
{
try
{
var type = objectToCheck.GetType();
return type.GetMethod(methodName) != null;
}
catch(AmbiguousMatchException)
{
// ambiguous means there is more than one result,
// which means: a method with that name does exist
return true;
}
}
Wouldn't it be better to not use any dynamic types for this, and let your class implement an interface.
Then, you can check at runtime wether an object implements that interface, and thus, has the expected method (or property).
public interface IMyInterface
{
void Somemethod();
}
IMyInterface x = anyObject as IMyInterface;
if( x != null )
{
x.Somemethod();
}
I think this is the only correct way.
The thing you're referring to is duck-typing, which is useful in scenarios where you already know that the object has the method, but the compiler cannot check for that.
This is useful in COM interop scenarios for instance. (check this article)
If you want to combine duck-typing with reflection for instance, then I think you're missing the goal of duck-typing.
To avoid AmbiguousMatchException, I would rather say
objectToCheck.GetType().GetMethods().Count(m => m.Name == method) > 0
I have a class named config with one string field named key.
When I apply the GET property of the class, the property has to return one variable key in different types (Int or bool or String).
I implemented it as follow:
public enum RetType {RetInt, RetBool, RetString};
...
public object PolimorphProperty(string key, RetType how)
{
get
{
switch (how)
{
case RetType.RetInt:
...;
case RetType.RetBool:
...;
case RetType.RetString:
...;
}
}
}
But the problem that PolimorphProperty returns Object type.
What should I change in the code to get the appropriate type (int,bool,string), not the object?
Do this:
public T PolimorphProperty<T>(string key)
{
return (T) objectInstanceHere;
}
Usage example:
int i = PolimorphProperty<int>("somekey");
And this supports the http://www.antiifcampaign.com/
As much as possible avoid switch, if for that matter, in a polymorphic code.
public T PolimorphProperty<T>(string key, T how)
{
//todo
}
Any type in C# is actually an object.
From what I understood from your question, you call your method this way:
PolimorpthProperty(key, RetType.SomeType)
The method returns an object. You should use it this way:
int key = (int)PolimorthProperty(key, RetType.RetInt);
This is called Unboxing.
How about this, consider that you original implementation of 'PolimorphProperty' remains im your project and you add this:
public TType PolimorphProperty<TType>(string key, RetType how)
{
return (TType)PolimorphProperty(key, how);
}
If I understood correctly, you are looking for something like this:
public T GenericMethod<T>(string key)
{
var ret = new object(); // Retrieve object from whatever...
return (T) ret;
}
public void UsageExample()
{
int typedResult = GenericMethod<int>("myKey");
}
If you are trying to fetch different objects based on the type T, with different logic, than you'll have to switch on types anyway, Because unless your collection supports objects of certain type (they usually do), the compiler doesn't know what to do.
In this case, check this question.
An object can provide its binding semantics by implementing
IDynamicMetaObject Provider—or more easily by subclassing
DynamicObject, which provides a default implementation of this
interface.
source
I never implemented this interface nor class and always been able to execute things dynamically:
public class aa
{
public void bbb()
{ }
}
dynamic a = new aa().bbb();
so what do they mean by this quote ?
im trying to understand when should i need to use IDynamicMetaObject or the DynamicObject inheritance
The dynamic keyword causes references to an object to be late-bound and only resolved at runtime. Usually, the reason for this is because you are using an IDynamicMetaObjectProvider implementer, which allows your code to decide how to treat the run-time property resolution. That is, you may want to add and remove properties at runtime (typically implemented as a dictionary, like ExpandoObject).
What your example code is doing is just preventing compile-type type checking. In fact it's worse than doing nothing, because if you wrote code that accessed a nonexistent property or method of your class, it would still compile, but of course crash at runtime. I can't think of many good reasons to refer to concrete classes with dynamic (expect for squishy typecasting or duck-typing, but we usually use interfaces for stuff like this in C#!)
Example implementation of a dynamic object that inherits DynamicObject from one of my own projects:
https://github.com/jamietre/IQObjectMapper/blob/master/source/IQObjectMapper/IQDynamicObject.cs
(It makes one call to a factory method that returns a new dictionary with options, all you need to do to make this non-dependent is change the constructor from:
InnerDict = ObjectMapper.MapperCache.GetDictionary<object>(Options);
to:
InnerDict = new Dictionary<string,object>();
and get rid of a couple conditons that check options
I hate to give "pithy" answers like this, because its not very imformative, but this really is a case of "if you needed it, you would know."
It is very rare that you would need to implement a dynamic object in an application, or even most library code. The interface is meant for people implementing classes that can only be used as dynamic objects; for example, if you wanted to implement Javascript-like behavior on your object. You can call any property or method you want on such an object, and it will compile. It's up to your implementation at run-time to figure out whether a given call works or not.
A totally pointless but descriptive example would be a class that decides which properties are valid based on the day of the week:
public class WeekendObject : DynamicObject
{
Dictionary<string, object> propertybag = new Dictionary<string, object>();
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
if (name.StartsWith("Sunday"))
{
return propertybag.TryGetValue(name, out result);
}
}
else
{
if (!name.StartsWith("Sunday"))
{
return propertybag.TryGetValue(name, out result);
}
}
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
if (name.StartsWith("Sunday"))
{
propertybag[binder.Name.ToLower()] = value;
return true;
}
}
else
{
if (!name.StartsWith("Sunday"))
{
propertybag[binder.Name.ToLower()] = value;
return true;
}
}
return false;
}
}
I have an object, MySession, that has a hashtable for storing arbitrary properties with arbitrary types. The relevant part of the object definition is:
public class MySession
{
private Hashtable _sessionVars;
///
/// Set and retrieve session variables ala the traditional session managers.
/// So, SessionObject["var1"] can be used to set or retrieve a value for var1.
///
/// Name of the variable to access.
/// An object that was stored in the session under key.
public object this[string key] {
get {
if (_sessionVars.ContainsKey(key)) {
return this._sessionVars[key];
}
return null;
}
set {
if (this._sessionVars.ContainsKey(key)) {
this._sessionVars.Remove(key);
}
this._sessionVars[key] = value;
}
}
}
The annoying thing is that I have to properly cast the properties when I want to use them. For example:
MySession session = new MySession();
if ( (bool)session["valid"] == true ) { /* do something fun */ }
I would rather be able to do:
MySession session = new MySession();
if ( session["valid"] == true ) { /* do something fun */ }
Is it possible to do this in C#? If so, how?
Update: I do not want to use explicit methods for accessing the properties. The point is to be able to access them as simply as possible. Not like session.GetProperty(name, type) or something.
If you think carefully, you will realize that this is inherently impossible.
What if you write session[someTextbox.Text]?
What if you assign two different types to the same identifier?
Compiling such code would involve solving the halting problem to figure out what type each string would have.
Instead, you could make a strongly-typed wrapper class around HttpContext.Current.Session with properties that include casts in their getters.
If you are using .Net Framework 4.0 then you can do it by deriving your MySession class from DynamicObject and overriding the necessary methods.
Here is the code:
public class MySession : DynamicObject
{
//Why not use Dictionary class?
private Hashtable _sessionVars = new Hashtable();
public override bool TrySetMember(SetMemberBinder binder, object value)
{
this[binder.Name] = value;
return true;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = this[binder.Name];
return true;
}
//You can make it private so that users do not use strings directly.
public object this[string key]
{
get
{
if (_sessionVars.ContainsKey(key))
{
return this._sessionVars[key];
}
return null;
}
set
{
if (this._sessionVars.ContainsKey(key))
{
this._sessionVars.Remove(key);
}
this._sessionVars[key] = value;
}
}
}
And this how you use it:
dynamic ses = new MySession();
ses.number = 5;
ses.boolean = true;
Console.WriteLine(ses.number > 4);
if (ses.boolean)
{
Console.WriteLine(ses.number - 1);
}
Console.ReadKey();
No need for casting or using string to access the new fields! If you are using Resharper you will get intellisense for existing fields too. If you need more functionality you can override other members too.
I personally end up having to handle the scenario where the session variable hasn't been set yet. Therefore, I end up with a method that looks like this:
public class MySession
{
...
public T GetValue<T>(string key, T defaultValue)
{
return _sessionVars.ContainsKey(key) ? this._sessionVars[key] as T : defaultValue;
}
}
Then T can be inferred. It can then be called like this (no casting required):
if (mySession.GetValue("valid", false))
{
// fun stuff here
}
I'm not really sure is "as T" works. If not, you can cast it to (T) done that before. "as T" would be nice if you've got inherited classes and such.
I typically derive off a class like mySession and call base.GetValue() in property getters I expose off the derived class.
If you're passing string (or any sort of object) keys, then it's impossible to do; the indexer method can only return one specific type, so you couldn't possible have it return a string or a double, for instance.
There are a couple of options: one, if this is a limited-scope class that doesn't need the flexibility of arbitrary keys, then you can just add explicit properties--maybe just for commonly used properties if you want to still be able to fall back on the object-returning indexer.
Or, you could add a generic Get method, like so:
public T GetValue<T>(object key) {
if(_hashSet[key] is T) {
return (T)_hashSet[key];
}
throw new InvalidCastException();
}
That doesn't get you much, though, since you'll still have to specify the type name, you're just moving it from the cast to the generic parameter.
EDIT: Of course, how you want to handle invalid casts is up to you, but throwing the exception mimics the behavior of the direct cast. As someone mentioned in another answer, if you also specify a parameter of type T in the signature, then it will get the correct type from that parameter.
Easy and best way to add session
public static void Add<T>(string key, T value)
{
var current = HttpContext.Current;
if (current == null) return;
current.Session.Add(key, value);
}
Example
public Model User
{
private string searchText
{
get { return SessionHelper.Get<string>("searchText"); }
set { SessionHelper.Add("searchText", value); }
}
}
In javascript you can detect if a property is defined by using the undefined keyword:
if( typeof data.myProperty == "undefined" ) ...
How would you do this in C# using the dynamic keyword with an ExpandoObject and without throwing an exception?
According to MSDN the declaration shows it is implementing IDictionary:
public sealed class ExpandoObject : IDynamicMetaObjectProvider,
IDictionary<string, Object>, ICollection<KeyValuePair<string, Object>>,
IEnumerable<KeyValuePair<string, Object>>, IEnumerable, INotifyPropertyChanged
You can use this to see if a member is defined:
var expandoObject = ...;
if(((IDictionary<String, object>)expandoObject).ContainsKey("SomeMember")) {
// expandoObject.SomeMember exists.
}
An important distinction needs to be made here.
Most of the answers here are specific to the ExpandoObject which is mentioned in the question. But a common usage (and reason to land on this question when searching) is when using the ASP.Net MVC ViewBag. That's a custom implementation/subclass of DynamicObject, which won't throw an Exception when you check any arbitrary property name for null. Suppose you might declare a property like:
#{
ViewBag.EnableThinger = true;
}
Then suppose you wanted to check its value, and whether it's even set - whether it exists. The following is valid, will compile, won't throw any exceptions, and gives you the right answer:
if (ViewBag.EnableThinger != null && ViewBag.EnableThinger)
{
// Do some stuff when EnableThinger is true
}
Now get rid of the declaration of EnableThinger. Same code compiles and runs properly. No need for reflection.
Unlike ViewBag, ExpandoObject will throw if you check for null on a property that doesn't exist. In order to get MVC ViewBag's gentler functionality out of your dynamic objects, you'll need to use an implementation of dynamic that doesn't throw.
You could simply use the exact implementation in MVC ViewBag:
. . .
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = ViewData[binder.Name];
// since ViewDataDictionary always returns a result even if the key does not exist, always return true
return true;
}
. . .
https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Mvc/DynamicViewDataDictionary.cs
You can see it being tied into MVC Views here, in MVC ViewPage:
http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/ViewPage.cs
The key to DynamicViewDataDictionary's graceful behavior is the Dictionary implementation on ViewDataDictionary, here:
public object this[string key]
{
get
{
object value;
_innerDictionary.TryGetValue(key, out value);
return value;
}
set { _innerDictionary[key] = value; }
}
https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Mvc/ViewDataDictionary.cs
In other words, it always returns a value for all keys, regardless of what's in it - it simply returns null when nothing's there. But, ViewDataDictionary has the burden of being tied to MVC's Model, so it's better to strip out just the graceful dictionary parts for use outside MVC Views.
It's too long to really post all the guts here - most of it just implementing IDictionary - but here's a dynamic object (class DDict) that doesn't throw for null checks on properties that haven't been declared, on Github:
https://github.com/b9chris/GracefulDynamicDictionary
If you just want to add it to your project via NuGet, its name is GracefulDynamicDictionary.
I wanted to create an extension method so I could do something like:
dynamic myDynamicObject;
myDynamicObject.propertyName = "value";
if (myDynamicObject.HasProperty("propertyName"))
{
//...
}
... but you can't create extensions on ExpandoObject according to the C# 5 documentation (more info here).
So I ended up creating a class helper:
public static class ExpandoObjectHelper
{
public static bool HasProperty(ExpandoObject obj, string propertyName)
{
return obj != null && ((IDictionary<String, object>)obj).ContainsKey(propertyName);
}
}
To use it:
// If the 'MyProperty' property exists...
if (ExpandoObjectHelper.HasProperty(obj, "MyProperty"))
{
...
}
UPDATED: You can use delegates and try to get a value from the dynamic object property if it exists. If there is no property, simply catch the exception and return false.
Take a look, it works fine for me:
class Program
{
static void Main(string[] args)
{
dynamic userDynamic = new JsonUser();
Console.WriteLine(IsPropertyExist(() => userDynamic.first_name));
Console.WriteLine(IsPropertyExist(() => userDynamic.address));
Console.WriteLine(IsPropertyExist(() => userDynamic.last_name));
}
class JsonUser
{
public string first_name { get; set; }
public string address
{
get
{
throw new InvalidOperationException("Cannot read property value");
}
}
}
static bool IsPropertyExist(GetValueDelegate getValueMethod)
{
try
{
//we're not interesting in the return value. What we need to know is whether an exception occurred or not
getValueMethod();
return true;
}
catch (RuntimeBinderException)
{
// RuntimeBinderException occurred during accessing the property
// and it means there is no such property
return false;
}
catch
{
//property exists, but an exception occurred during getting of a value
return true;
}
}
delegate string GetValueDelegate();
}
The output of the code is the following:
True
True
False
I answered a very similar question recently: How do I reflect over the members of dynamic object?
Shortly, ExpandoObject is not the only dynamic object you might get. Reflection would work for static types (types that do not implement IDynamicMetaObjectProvider). For types that do implement this interface, reflection is basically useless. For ExpandoObject, you can simply check whether the property is defined as a key in the underlying dictionary. For other implementations, it might be challenging and sometimes the only way is to work with exceptions. For details, follow the link above.
Why you do not want to use Reflection to get set of type properyes? Like this
dynamic v = new Foo();
Type t = v.GetType();
System.Reflection.PropertyInfo[] pInfo = t.GetProperties();
if (Array.Find<System.Reflection.PropertyInfo>(pInfo, p => { return p.Name == "PropName"; }). GetValue(v, null) != null))
{
//PropName initialized
}
This extension method checks for the existence of a property and then returns the value or null. This is useful if you do not want your applications to throw unnecessary exceptions, at least ones you can help.
public static object Value(this ExpandoObject expando, string name)
{
var expandoDic = (IDictionary<string, object>)expando;
return expandoDic.ContainsKey(name) ? expandoDic[name] : null;
}
If can be used as such :
// lookup is type 'ExpandoObject'
object value = lookup.Value("MyProperty");
or if your local variable is 'dynamic' you will have to cast it to ExpandoObject first.
// lookup is type 'dynamic'
object value = ((ExpandoObject)lookup).Value("PropertyBeingTested");
Depending on your use case, if null can be considered as being the same as undefined, you can turn your ExpandoObject into a DynamicJsonObject.
dynamic x = new System.Web.Helpers.DynamicJsonObject(new ExpandoObject());
x.a = 1;
x.b = 2.50;
Console.WriteLine("a is " + (x.a ?? "undefined"));
Console.WriteLine("b is " + (x.b ?? "undefined"));
Console.WriteLine("c is " + (x.c ?? "undefined"));
Output:
a is 1
b is 2.5
c is undefined
(authorDynamic as ExpandoObject).Any(pair => pair.Key == "YourProp");
Hey guys stop using Reflection for everything it costs a lots of CPU cycles.
Here is the solution:
public class DynamicDictionary : DynamicObject
{
Dictionary<string, object> dictionary = new Dictionary<string, object>();
public int Count
{
get
{
return dictionary.Count;
}
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
string name = binder.Name;
if (!dictionary.TryGetValue(binder.Name, out result))
result = "undefined";
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
dictionary[binder.Name] = value;
return true;
}
}
Try this one
public bool PropertyExist(object obj, string propertyName)
{
return obj.GetType().GetProperty(propertyName) != null;
}