How do we check whether a dynamic clay object has a property?

烂漫一生 提交于 2020-01-15 05:53:09

问题


I have a dynamic object, that I think is implemented with Clay. It has one of two possible property names. I want to use which ever property name is available. The following doesn't work:

dynamic workItemPart = item.WorkItem; // is an Orchard.ContentManagement.ContentPart
var learnMore = workItemPart.LearnMore ?? workItemPart.LearnMoreField;

It throws a Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:

does not contain a definition for 'LearnMore'

How do we check if a dynamic Clay object has a property? In JavaScript, for instance, we can do the following.

var workItemPart = {
    LearnMoreField: "Sure"    
    }
console.log(workItemPart.LearnMore || workItemPart.LearnMoreField);

Is there anything this concise in C# with Clay?

Related:

Is Orchard.ContentManagement.ContentPart implemented with Clay?

https://twitter.com/bleroy/status/497078654405312512


回答1:


You can also use the indexed approach:

var learnMore = workItemPart["LearnMore"] != null ? 
     workItemPart.LearnMore : workItemPart.LearnMoreField;

Hope this helps.

UPDATE

I'm not sure why it doesn't. Both methods should work.

        dynamic New = new ClayFactory();
        var person = New.Person();
        person.skill = "Outstanding";
        var talent = person.talent;
        var talentTwo = person["talent"];
        var skill = person.talent ?? person.skill;
        Console.WriteLine(skill);
        skill = person.skill ?? person.talent;
        Console.WriteLine(skill);

Perhaps it is Orchard throwing you a curveball ...

Interesting enough, the null-coalesce operator does not process the first test case correctly. However, the standard test succeeds:

        skill = person.talent != null ? person.talent : person.skill;
        Console.WriteLine(skill);

Not sure what to advise you at this point.




回答2:


You can use an extension method to check if property exists:

public static class Extensions
{
    public static bool HasProperty(this object d, string propertyName)
    {
        return d.GetType().GetProperty(propertyName) != null;
    }
}

Usage:

bool hasProperty = Extensions.HasProperty(workItemPart, "LearnMore");

var learnMore =  hasProperty ? workItemPart.LearnMore : workItemPart.LearnMoreField;

It doesn't look like an extension method though.. since the workItemPart is dynamic you need to call it explicitly by specifying the class name.




回答3:


@Shaun Luttin, quite an old issue in the context of the Orchard cms, but recently I've proposed this pull request that has been committed

So, now you can use the following without throwing an exception

    if (contentItem.SomePart != null)
    if (part.SomeField != null)

The ContentItem and ContentPart classes inherit from System.Dynamic.DynamicObject and override the TryGetMember() method. And, before, if no property found the method returned false

    return false;

Now, even if the result object (the out parameter of the method) is set to null, the method return true which prevents from throwing an exception

    result = null;
    return true;

For more details, see the related PR link above

Best



来源:https://stackoverflow.com/questions/25149535/how-do-we-check-whether-a-dynamic-clay-object-has-a-property

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!