Is there a way to use the extension method in an object initializer block in C #

The simple demo below reflects what I'm trying to do. In a real program, I have to use the object initialization block, since it reads the list in the LINQ to SQl expression, and there is a value that I want to read from the database and save on the object, but the object does not have a simple property that I can set for this values. Instead, it has an XML data store.

It seems like I cannot call the extension method in the object initialization block and that I cannot attach the property using extension methods.

So I have no luck with this approach? The only alternative seems to be to convince the owner of the base class to change it for this scenario.

I have an existing solution where I subclass BaseDataObject, but this one also has problems that are not displayed in this simple example. Objects are saved and restored as BaseDataObject - casts and tests will be complex.

public class BaseDataObject { // internal data store private Dictionary<string, object> attachedData = new Dictionary<string, object>(); public void SetData(string key, object value) { attachedData[key] = value; } public object GetData(string key) { return attachedData[key]; } public int SomeValue { get; set; } public int SomeOtherValue { get; set; } } public static class Extensions { public static void SetBarValue(this BaseDataObject dataObject, int barValue) { /// Cannot attach a property to BaseDataObject? dataObject.SetData("bar", barValue); } } public class TestDemo { public void CreateTest() { // this works BaseDataObject test1 = new BaseDataObject { SomeValue = 3, SomeOtherValue = 4 }; // this does not work - it does not compile // cannot use extension method in the initialiser block // cannot make an exension property BaseDataObject test2 = new BaseDataObject { SomeValue = 3, SomeOtherValue = 4, SetBarValue(5) }; } } 

One of the answers (from mattlant) suggests using a free way to expand the style of the interface. eg:.

  // fluent interface style public static BaseDataObject SetBarValueWithReturn( this BaseDataObject dataObject, int barValue) { dataObject.SetData("bar", barValue); return dataObject; } // this works BaseDataObject test3 = (new BaseDataObject { SomeValue = 3, SomeOtherValue = 4 }).SetBarValueWithReturn(5); 

But will this work in a LINQ query?

+6
c # linq extension-methods initializer
source share
6 answers

Even better:

 public static T SetBarValue<T>(this T dataObject, int barValue) where T : BaseDataObject { dataObject.SetData("bar", barValue); return dataObject; } 

and you can use this extension method for derived BaseDataObject types for chain methods without casting and saving the actual type when outputting to a var or anonymous type field.

+3
source share

Object initializers are just syntactic sugar that requires a smart compiler, and with the current implementation, you cannot call methods in the initializer.

 var x = new BaseDataObject { SomeValue = 3, SomeOtherValue = 4 }; 

The compiler will get something like this:

 BaseDataObject tempObject = new BaseDataObject(); tempObject.SomeValue = 3; tempObject.SomeOtherValue = 4; BaseDataObject x = tempObject; 

The difference is that there can be no problems with synchronization. The variable x receives the immediately assigned BaseDataObject; you cannot tinker with the object during its initialization.

You can simply call the extension method after creating the object:

 var x = new BaseDataObject { SomeValue = 3, SomeOtherValue = 4 }; x.SetBarValue() 

You can change SetBarValue as a property with get / set, which can be assigned during initialization:

 public int BarValue { set { //Value should be ignored } } 

Or you can subclass / use the facade template to add a method to your object:

 public class DataObjectWithBarValue : BaseDataObject { public void BarValue { set { SetData("bar", value); } get { (int) GetData("bar"); } } } 
+4
source share

No, but you could do it ....:

 BaseDataObject test2 = (new BaseDataObject { SomeValue = 3, SomeOtherValue = 4}).SetBarValue(5); 

ANd so that your extension returns an object, for example Linq Does.

EDIT: That was a good idea until I re-read and saw that the base class was developed by a third party: otherwise you have no code. Others here posted the correct solution.

+4
source share
  static T WithBarValue<T>(this T dataObject, int barValue) where T : BaseDataObject { dataObject.SetData("bar", barValue); return dataObject; } var x = new BaseDataObject{SomeValue=3, OtherValue=4}.WithBarValue(5); 
+1
source share

Does the class extend the opportunity? Then you can easily add the required property.

Otherwise, you can create a new class with similar properties that simply access a private instance of the class you are interested in.

0
source share

That's right, after learning from the defendants, a short answer to the question "Is there a way to use the extension method in the object initializer block in C #?" " No. "

The way I ended up solving the problem I came across (similar, but more complicated, that the toy problem I asked here) was a hybrid approach, as follows:

I created a subclass like

 public class SubClassedDataObject : BaseDataObject { public int Bar { get { return (int)GetData("bar"); } set { SetData("bar", value); } } } 

Which works great in LINQ, the initialization block looks like

  SubClassedDataObject testSub = new SubClassedDataObject { SomeValue = 3, SomeOtherValue = 4, Bar = 5 }; 

But the reason I did not like this approach, first of all, is that these objects are placed in XML and returned as BaseDataObject, and discarding will be annoying, an unnecessary copy of the data and put two copies of the same object in the game.

In the rest of the code, I ignored subclasses and applied extension methods:

  public static void SetBar(this BaseDataObject dataObject, int barValue) { dataObject.SetData("bar", barValue); } public static int GetBar(this BaseDataObject dataObject) { return (int)dataObject.GetData("bar"); } 

And it works well.

0
source share

All Articles