user3604459
user3604459

Reputation: 11

Name is bound to a method and cannot be used like a property

I am working on a WCF service app for my job where I take an XML and convert it to PRX. I have hit a major snag. Here is my code:

public string ConvertXMLtoPRX(string theXml) //method to convert the incoming xml file to prx format
{

    dynamic aXml = XDocument.Parse(theXml);             //parse the XML that has been passed into the method
    var mProposalMstr = aXml.Root.Element("ProposalMstr");

    if (mProposalMstr == null)                                       //check to see if the root element in the incoming XML is present
        throw new Exception("Cannot be converted to PRX - element ProposalMstr not found.");  //exception to be thrown if the root element is not present 

    System.Text.StringBuilder tempPrxString = new System.Text.StringBuilder();               //new StringBuilder object to take in incoming text from the xml file
    tempPrxString.Append("StartApp");                                //First part of the PRX file
    tempPrxString.Append(System.Environment.NewLine);

    foreach (XElement thisElem in aXml.Elements)                                 //loop through each element in the XML file
        tempPrxString.AppendLine("Field|" + thisElem.Name + "|" + thisElem.Value);           //builds upon the PRX string for each node in the XML file

    tempPrxString.AppendLine("EndRecord|");                          //end of the PRX string

    return tempPrxString.ToString();                                //return the prx string 
}

When it gets to the foreach loop, it hits a runtime error saying "The name 'Elements' is bound to a method and cannot be used like a property."

I have been looking everywhere and cannot find a workaround for this. Does anyone have any suggestions? Thanks in advance for any help.

Upvotes: 1

Views: 3231

Answers (1)

binki
binki

Reputation: 8316

This is because aXml is an XDocument. If you look at the documentation, you will see that XDocument.Elements is inherited from XContainer.Elements and that it turns out to be a method that accepts no arguments. To invoke a method that accepts no arguments, you still have to specify an empty parameter list (the parentheses):

foreach (XElement thisElem in aXml.Elements());

dynamic

You might be wondering why this throws an error at runtime rather than at compiletime. The dynamic keyword tells the C# compiler that it cannot perform type checking against the modified expression or variable. Instead, type checking and resolution will be performed at runtime. This is useful when you cannot know the type ahead of time but want to still use “normal”-looking syntax to interact with it.

Perhaps you cannot predict the type that is returned by a method. For example, its signature says that object is returned but you know that the object will have a property with a particular name. This pattern might make sense if you find making a plain old data class too much work and want to just return an anonymous type:

static object doSomething()
{
    // Even though it’s a lie…
    return new { IsFoodTasty = true, FoodType = "Angelfood Cake", };
}

public static void Main()
{
    dynamic foodInfo = doSomething();
    Console.WriteLine(foodInfo.IsFoodTasty ? "Food {0} tastes good." : "Food {0} tastes bad.", foodInfo.FoodType);
}

Another use for dynamic is to give prettier access to an ExpandoObject or DynamicObject. E.g.,

public static void Main()
{
    // I am building something like an ASP.NET MVC ViewBag…
    // Though, there are myriad reasons why you should prefer
    // typed views ;-).
    dynamic bag = new ExpandoObject();
    bag.Name = "Joe";
    bag.RandomThing = "Ridiculousness.";
    DoSomething(bag);
}

static void DoSomething(dynamic bag)
{
    Console.WriteLine("Hi, {0}.", bag.Name);
}

Avoid dynamic

However, in your case, you and the C# compiler can very easily guess what the type of XDocument.Parse(string) will be—namely, XDocument. You have two better options. Either tell the C# compiler that you expect XDocument.Parse(string) to return XDocument by writing XDocument aXml = XDocument.Parse(theXml); or let the C# compiler do the inference for you by writing var aXml = XDocument.Parse(theXml);. If you use var, the compiler will automatically set the compiletime type of aXml to XDocument. Regardles of whether you use var or XDocument, you should now this error at compiletime instead of runtime:

1>c:\users\ohnob\documents\visual studio 2015\Projects\ConsoleApplication4\ConsoleApplication4\Program.cs(28,39,28,52): error CS0446: Foreach cannot operate on a 'method group'. Did you intend to invoke the 'method group'?

Yay! The compiler has caught your error and you have escaped from a confusing runtime crash! Now you can add in the missing () and try compiling again…

In general, when you can, you should avoid using the dynamic keyword. C# has very strong facilities for helping you use static typing. For example, var exists, generics support exists, anonymous types support exists, et cetera. Putting dynamic or type casting into your code means that the type checking the C# compiler would normally perform is deferred until runtime. This makes it easier to write code that compiles fine but fails unpredictably at runtime. It even has implications for performance, so even if dynamic makes a particular chunk of code easier to read, it might not be appropriate in a tight loop.

Upvotes: 2

Related Questions