PDA

View Full Version : Initializing read only properties in a derived class' constructor?



tolgaerdogus
Feb 04, 2017, 8:41 PM
How come the following code can set a read only property "Reader":

new ext.Store()
{

ID = "store",
Proxy =
{

new ext.RestProxy()
{
Url = "/infohubuser",
Reader = {
new ext.JsonReader()
{

RootProperty="data",
//SuccessProperty = "success",
MessageProperty = "message"
}
},
Writer =
{
new ext.JsonWriter()
{
//Encode = true,
//RootProperty="data"
AllowSingle = true

}
},

}
},

But I can't seem to set it in a derived class constructor as such:

public class InfoHubUserProxy : AjaxProxy
{
public InfoHubUserProxy(): base()
{

Url = "/infohubuser";
Reader = ...
}

}

And how come the API property of RestProxy is not available to set in the first code block?
I am hoping to code all of my UI classes through a simple subclassing of the most fitting class but it seems the config property visibilities are not the same there and some properties are not able to be set...

Thanks

tolgaerdogus
Feb 06, 2017, 1:47 PM
Ok - it seems intellisense is getting messed up and API is indeed available as a property in RestProxy (inherited from abstract base class ServerProxy), however since it has only a getter, again it is nonassignable. How would I initialize the API and Reader properties that only have getters, inside of the constructor for a derived class from RestProxy?

Thanks

fabricio.murta
Feb 07, 2017, 12:38 AM
Hello again!

Check out these two examples:

- DataView - Advanced - Multi Sort (http://mvc4.ext.net/#/DataView_Advanced/Multi_sort/)
- GridPanel - Update - Restful (http://mvc4.ext.net/#/GridPanel_Update/Restful/)

Remember, the examples explorers are your friends (both MVC and WebForms ones). You can grab them from github:
- WebForms Examples Explorer (https://github.com/extnet/Ext.NET.Examples/)
- MVC Examples Explorer (https://github.com/extnet/Ext.NET.Examples.MVC/)

Hope this helps!

tolgaerdogus
Feb 07, 2017, 1:12 PM
Fabricio,

thanks for your continued help - I really appreciate it.

I guess, put more clearly, what I am looking for is how to get around the compilation problem due to the Reader and API properties having getters only:


Error CS0200 Property or indexer 'ServerProxy.API' cannot be assigned to -- it is read only AdminToolWeb
Error CS0200 Property or indexer 'ServerProxy.Reader' cannot be assigned to -- it is read only AdminToolWeb



public class InfoHubUserProxy : RestProxy
{
public InfoHubUserProxy() : base()
{
Store s = new Store();
Model m = new Model();

Url = "/infohubuser";
Reader = new ReaderCollection
{
new ext.JsonReader()
{

RootProperty = "data",
//SuccessProperty = "success",
MessageProperty = "message"
}
};
API = new CRUDUrls()
{
Read = "",
Update = "",
Create = "",
Destroy = ""
};
}

}

tolgaerdogus
Feb 07, 2017, 1:58 PM
There may be sophisticated reasons why these "readonly" properties were declared with only a getter, however I think it would be better to declare them with an auto property getter and private setter, thus derived classes would be able to set the value inside of constructors as per c# 6.0 spec.

In the absence of that, I have found that the following works since the getters are at least declared with the virtual keyword and are hence overridable:


public class InfoHubUserProxy : RestProxy
{
public override CRUDUrls API { get; }
public override ReaderCollection Reader { get; }
public override WriterCollection Writer { get; }
public InfoHubUserProxy() : base()
{
Store s = new Store();
Model m = new Model();

Url = "/infohubuser";
Reader = new ReaderCollection
{
new ext.JsonReader()
{

RootProperty = "data",
//SuccessProperty = "success",
MessageProperty = "message"
}
};
Writer = new WriterCollection
{
new ext.JsonWriter()
{
//Encode = true,
//RootProperty="data"
AllowSingle = true

}
};
API = new CRUDUrls()
{
Read = "read",
Update = "update",
Create = "create",
Destroy = "destroy"
};
}

}

Please do let me know if I am not supposed to be doing this or there is a better way to accomplish this...

Thanks

fabricio.murta
Feb 07, 2017, 9:45 PM
Hello @tolgaerdogus!

I think I misunderstood your initial question, and the examples don't really show the main point, which is extending the component.

But yes, your conclusion is right! These properties are defined with getter only exactly to allow extending it, maybe not exactly as you are extending, but to allow, for example, for you to make a derived class from the Ext.Net.JsonReader and provide it as argument to the main component without having to override the whole component. This was mainly thought of based on experience with components that use a store, to allow users to extend them with ease.

This have been done way before C# 6 specification were out, and we maintain backwards compatibility with previous C# versions so, we can't just apply them currently -- unless we code them with preprocessor macros.

Your conclusion looks sane and if it works for you, well, it really does work for us! But I'll give your first question again a thought to see if I can get down to a simpler or just different approach or conclusion you got to.

fabricio.murta
Feb 07, 2017, 10:25 PM
Alright, hello again! Let me try to put this in easier words:

What you need is, make a sub-class that would auto-set the (for example) Reader for your component?

For example, you have to do this same reader to several other components, so you want just to "bundle" this on a sub class:



var RestProxy = new RestProxy() {
Url = "www.ext.net",
Reader = {
new JsonReader()
{
RootProperty = "mypro",
MessageProperty = "msgpro"
}
}
};


So you could do something like this:



var MyRestProxy = new MyProxy() {
Url = "www.ext.net"
};


And just have it with the same reader of the base RestProxy class?

For this, you would have to declare your class like that:



public class MyProxy : RestProxy
{
public MyProxy() : base()
{
this.Reader.Add(new JsonReader()
{
RootProperty = "mypromy",
MessageProperty = "msgpromy"
});
}
}


In other words, the collection would already be a thing when the class constructor is called, so you have just to add the reader to the collection.



public class MyProxy : RestProxy
{
public MyProxy() : base()
{
this.Reader.Add(new JsonReader()
{
RootProperty = "mypromy",
MessageProperty = "msgpromy"
});
}
}


This would though result in an error at run-time if your derived class is initialized with the reader provided in the constructor "sugar" like this:



var MyRestProxy = new MyProxy()
{
Url = "www.ext.net",
Reader = {
new JsonReader()
{
RootProperty = "mypro",
MessageProperty = "msgpro"
}
}
};


This is because the way above is the same of:



var MyrestProxy = new MyProxy();
MyrestProxy.Url = "www.ext.net";
MyrestProxy.Reader.Add(new JsonReader()
{
RootProperty = "mypro",
MessageProperty = "msgpro"
});


And there's no way to tell the constructor the reader was specified with the constructor using the object initializer syntax (https://msdn.microsoft.com/en-us/library/bb384062.aspx).

I hope now the response is more in the lines of your actual question!