C# Hiding fields from model where xml deserialization points to - c#

sI have one controller class, which is having private field of another class which is a model, model which gets data from xml deserialization. Because of this deserialization process I had to create public, parameterless constructor and some public fields-helpers which are simply processing data formats to another types. This processing is so simple that I don't want to re-write and XmlSerialization class using it's interface.
What I want to achieve is to have access to the fields from the model from the interface it inherits from only, but the model has to have public fields - how to hide some of them? They are in the same project. (Whole application is so tiny that dividing it to smaller pieces not always makes sense).
There is an example:
public class Program
{
public static void RequestHandler
{
public RequestHandler(string xmlRequest){
IRequest request = DataModel.ParseXml(xmlRequest);
//now user can use request from IRequest only
//but when he doesn't know that he has to use IRequest he can easily access and change
//values in DataModel properties, I want to prevent such possibility
}
}
}
public interface IRequest{
int test_id { get; }
DateTime description { get; }
IRequest ParseXml(string request);
bool Validate(IRequest request);
}
public class DataModel : IRequest {
[XmlElement("testId")]
int test_id { get; set; }
[XmlElement("testId")]
DateTime description { get; set; }
public DataModel() {} //this has to be specified to be allowed to use Serialization
//I don't want users to be able to use this constructor, however it has to be public
IRequest static ParseXml(string request){
// Xml Parsing process
}
bool Validate(IRequest request) {
//Process of checking if all data are available
}
}

Can you make your model as 'Internal' and expose all fields only via multiple interfaces and write another class which will expose your model objects via interface. e.g.
internal class DataModel : Interface1, Interface2 {
internal DataModel(_xml)
{
this.xml = _xml;
}
private xml {get; set;}
public Interface1.Property1 {get; set;}
public Interface2.Property2 {get; set;}
}
//expose DataModel only via below Helper class
public class DataModelHelper {
public Interface1 GetModel_1(string xml)
{
Interface1 i1 = new DataModel(xml);
return i1;
}
public Interface2 GetModel_2(xml)
{
Interface2 i2 = new DataModel(xml);
return i2;
}
}

Related

C# : make derived object conditionally share same base object

I have a base class with is inherited by multiple derived classes. I am initializing some properties of base class in constructor. Is there any way i can make the base class property being shared by my derived objects rather than creating the same property values for each derived class object. This is really important because some of the base class property values are generated by services and sharing this can improve performance.
Below is somewhat a simple blueprint of what i am trying to say:
public class ClassA
{
//i dont want to use static here as it will be shared for multiple codes
protected string country { get; set; }
public ClassA(string code)
{
country = CallsomeService(code);
}
}
public class ClassB : ClassA
{
public ClassB(string code) : base(code)
{
//blah blah
}
public void DomeSomethingWithCountry()
{
Console.WriteLine($"doing this with {country} in classB");
}
}
public class ClassC : ClassA
{
public ClassC(string code) : base(code)
{
//blah blah
}
public void DomeSomethingWithCountry()
{
Console.WriteLine($"doing soemthing else with {country} in classC");
}
}
Now making objects like below
public void test()
{
//call service for this
var classb=new ClassB("1");
//dont call service for this
var classc=new ClassC("1");
classb.DomeSomethingWithCountry();
classc.DomeSomethingWithCountry();
//call service for this as code is different
var classb1=new ClassB("2");
}
You could store the result of having made the call statically, rather than the value itself.
public class ClassA
{
static Dictionary<string,string> codeToCountryLookup
= new Dictionary<string,string>();
protected string country { get; set; }
public ClassA(string code)
{
if(!codeToCountryLookup.ContainsKey(code))
codeToCountryLookup.Add(code,CallsomeService(code));
country = codeToCountryLookup[code];
}
}
This is not in any way threadsafe, but should give you somewhere to start.

Get class name from the class who extend it

I have a class like this
public class BaseClass
{
public string Request { get; set;}
}
and I have the class like this :
public class ExtendClass : BaseClass
{
}
So actually the property Request will always be set with the name of ExtendClass. So it actually will be Request="ExtendClass"
I have many class who extend BaseClass. I know I just can pass string to it, but is that possible to do it?
You can use object.GetType which will always return the type on top in the hierarchy (so the last deriving class):
public string Request
{
get
{
return this.GetType().Name;
}
}
Name will return the short type name, without the namespace. If you want that too, you should use FullName.
You have multiple choices. For example, you can use reflections:
public string Request { get {return this.GetType().Name; }}
Or you can make it more explicit, with abstract property (and that way you can specify not only class names):
public abstract class BaseClass
{
public abstract string Request { get; }
}
class ExtendClass : BaseClass
{
public override string Request { get {return "ExtendClass"; } }
}

ServiceStack: Property in request DTO becomes null if type is abstract

I have a ServiceStack 3-based client-server architecture. I'm trying to create a service whose request DTO contains a property with an abstract type, with two different concrete classes implementing it. The abstract type could be either an abstract class or an interface; however, in either case, the server receives a null object in the property.
There's three assemblies and corresponding namespaces: TestClient, Server, and CommonLib referenced by both client and server.
That is, spread across the three assemblies:
namespace CommonLib.Services
{
public class GetThing : IReturn<GetThingResponse> // request DTO
{
public IThisOrThat Context { get; set; }
}
public class GetThingResponse
{
public Dictionary<int, string> Result { get; private set; }
public GetThingResponse(Dictionary<int, string> result) // response DTO
{
Result = result;
}
}
}
namespace CommonLib
{
public interface IThisOrThat { }
public class This : IThisOrThat { } // and so forth
}
namespace Server.Services
{
public class GetThing Service : IService
{
public object Get(GetThing request)
{
var foo = request.Context; // this is null
}
}
}
namespace TestClient
{
class Program
{
public const string WSURL = "http://localhost:61435/";
static void Main(string[] args)
{
using (var client = new JsonServiceClient(WSURL))
{
var result = client.Get(new GetThing
{
Context = new CommonLib.This("context info")
});
}
}
If I change the Context property in GetThing to be of type This instead of IThisOrThat, this works. Leaving it as the interface, or changing IThisOrThat to be an abstract class, results in the data being transmitted as null.
I'm assuming this is a serialization problem. I've tried changing the interface to an abstract class and decorating that with appropriate KnownType attributes, but ServiceStack's serializer doesn't appear to benefit from this. Is there any trick to get this done?
You would need to enable JsConfig.IncludeTypeInfo = true; on the client side, so the serializer includes the type information with the request. This will add an extra property (__type) with the type definition so the service knows what to type it as.
It fails currently because requests by default don't provide type information to deserialize the object into the class that implements the interface. This was an issue that was previously raised.
The problem is the when the JSON client makes the request, it will serialize up the a class that implements IThisOrThat such as your This class. But when it gets to the other end ServiceStack.Text doesn't know what to deserialize the object into. The type information is lost so it doesn't know what kind of IThisOrThat it is. So without the additional __type information property in the request this is happening:
Scenario:
interface ISomething
{
string Name;
}
class MySomething : ISomething
{
public string Name { get; set; }
public int Age { get; set; }
}
class MySomethingElse : ISomething
{
public string Name { get; set; }
public int Size { get; set; }
}
Then you make the call from your JsonServiceClient using a typed object
client.Get(new MySomething { Name: "Duck", Age: 20 });
The JSON that is sent would be { "Name":"Duck", "Age":20 } what type does the deserialiser choose now? It could be an MySomething or a MySomethingElse, or even another ISomething that it just doesn't know about yet. So because it can't decide the result is simply null.
Generally interfaces and DTOs don't mix, see here.
I had a similar problem, and realized i didn't have { get; set; } applied to the response DTO, so the result of my object was always null...
Thought this information could also help anyone searching for this ...

Accessing Properties or a Parent Class from Base

I am attempting to create an application which interacts with a database.
I program in many languages and I loved how easy it was to use Models in an MVC based application.
So my question is, trying to replicate this functionality, I have 2 classes as follows:
Base Class:
public class BaseModel
{
protected string TableName { get; set; }
public BaseModel()
{
}
public void Save()
{
// Save data in derived class to table stored in TableName
}
}
Derived Class:
public class UserModel : BaseModel
{
public string Field1 { get; set; }
public string Field2 { get; set; }
public UserModel()
{
base.TableName = "user";
}
}
From my main application, i want to be able to do the following:
public class Class1
{
public Class1()
{
UserModel model = new UserModel();
model.Field1 = "Value1";
model.Field2 = "Value2";
model.Save();
}
}
Here is where i have hit a problem. I cannot for the life in me figure out, how i would be able to access the properties in UserModel so they can be saved to the database table specified in in the constructor of UserModel to the BaseModel.
Hope this made sense. :)
This code is not my working code, it is a very simple representation of what i would like to achieve so Fields and properties (validators etc) have been dumbed down for ease of reading.
I think that a more "real" example would actually help understand better, but I think that you should create a virtual (or even abstract) method in the base class to get the data to save in the database:
public class BaseModel {
protected virtual string GetDataToSaveInDB() {
// if it makes sense to have the data as a string...
}
public void Save() {
string data = GetDataToSaveInDB();
// do something with data...
}
}
Then you return the data in the derived classes:
public class UserModel : BaseModel {
protected override string GetDataToSaveInDB() {
return "Field1=" + Field1 + ";Field2=" + Field2;
}
}
This is just to illustrate the concept, if you provide more information it will be easier to provide a real answer.
How do you save the data in your DB? How is the structure to the table?
This is in general solved by utilize abstract functions at the base level and then overriding them with specifics in the derived class. So would would set up a call tree in the base but functions that need to know the details of the derived class would be implemented in the derived class.
public class BaseModel
{
protected string TableName { get; set; }
public BaseModel()
{
}
public abstract void Save();
}
In this case where you have one concrete data representation manifested in a base class it may be better to create a DTO object which your business classes take in a utilize. This is the approch of most of the frameworks like entity.

Polymorphism: getting it right

I'm trying to get my head around a polymorphism/inheritance situation in C#.
What I have right now is these classes:
Lease (the base class containing the general data)
PrivateLease (inheriting from the Lease class)
BusinessLease (inheriting from the Lease class)
What I want to achieve is this:
Lease lease = new PrivateLease();
This works at the moment, but I am not able to access the properties on the PrivateLease object when doing this. At least not without casting the Lease object to a PrivateLease object first.
I'd like the Lease object to be the general object of either a PrivateLease or BusinessLease object which holds all the data for one of the objects. Then when inserting/updating/deleting to the database I'm going to ask which type it is first to dertermine which tables to insert the data into.
I've got a strange feeling that the above is not the right approach to solve this problem. Does anyone have any hints on this? :-) I've searched on google and read in my programming books and everyone suggests this approach of having a base class and then inherit from it to the other classes.
Any help/hint is greatly appreciated!
Thanks in advance.
EDIT
Should've elaborated a bit on this from the beginning, I'm sorry for that!
The above mentioned classes are merely just holding data from the UI of my ASP.NET solution to perform CRUD operations against the database via a Data Access Layer. So bascially these classes only contains a bunch of properties to hold data. I.e:
public class Lease
{
public int Id { get; set; }
public bool IsActive { get; set; }
public string TypeOfRental { get; set; }
public string RentalPeriod { get; set; }
public DateTime TakeoverDate { get; set; }
}
public class PrivateLease : Lease
{
public string Floor { get; set; }
public string Side { get; set; }
public int FloorSize { get; set; }
public int NumberOfRooms { get; set; }
}
etc..
The PrivateLease and BusinessLease classes are different because of the different leaseing-variables that exists in the real world :-)
Basically I could just go with the two separate PrivateLease and BusinessLease objects, but since the model dictates that an Address object can hold one or more Leases, this is not an option.
To me it seems like I'm going to go through a major casting hell both on the ASP.NET frontend and on the DAL? :-/
Don't decide (choose a logic) on the layer of consumer, but let to decide by the classes themselves:
// or you ILease interface if a parent class will not contain any shared logic
abstract class Lease
{
public abstract void Do();
// example of shared logic
protected void Save(Lease l) { }
}
class PrivateLease : Lease
{
public override void Do() { // private logic here }
}
class BusinessLease : Lease
{
public override void Do() { // business logic here }
}
Usage:
Lease l = ...
l.Do(); // execute the logic
You may want to create a factory for objects creation:
static class LeaseFactory<T> where T : Lease, new() // constraint to require default constructor existence
{
public static Leas Create()
{
return new T();
}
}
You're right in the basic approach of having a base class.
What you need to do is to put any common properties in the base class. Then if you have different business rules, those can be implemented with virtual functions, being called polymorphically.
abstract class Lease
{
public int MonthlyCost {get;set;}
public string CustomerName {get;set;}
// Declare that all Leases have to have an IncreaseCost method.
public abstract void IncreaseCost();
}
class PrivateLease : Lease
{
// Private leases are incremented by an absolute number (10).
public override void IncreaseCost()
{
MonthlyCost += 10;
}
}
class BusinessLease : Lease
{
// Business leases are incremented by 10%.
public override void IncreaseCost()
{
MonthlyCost *= 1.10;
}
}
// Somewhere in your code...
Lease lease = new PrivateLease();
// This call is polymorphic. It will use the actual type of the lease object.
lease.IncreaseCost();
In the modern OOD you can use interfaces, for this situation.
Edit:
In my opinion, to avoid casting, you can have multiple interfaces for multiple purposes. then PrivateLease and BusinessLease can implement the appropriate ones.
interface IWrite
{
string Data { get; set; }
void Write();
}
interface IRead
{
string Data { get; set; }
void Read();
}
public class Lease
{
//..
}
public class PrivateLease : Lease, IWrite, IRead
{
// other implementations
public string Data { get; set; }
public void Read()
{
//..
}
public void Write()
{
//..
}
}
public class BusinessLease : Lease, IRead
{
// other implementations
public string Data { get; set; }
public void Read()
{
//..
}
}
In Lease class add virtual method called DBUpdate and override it in both the derived classes.
Let's say some Utility class has LeaseDBOperation Method looks like this :
public static void LeaseDBOperation (Lease anylease)
{
anyleaase.DBUpdate();
}
you can call this method as :
var pl = new PrivateLease();
..set all the properties of **pl**
//call this for db operations :
Utility.LeaseDBOperation(pl)
Here in LeaseDBOperation method , if based on the type send , DBUpdate method of required class will be called.
Lease l = (Lease)sth;
if (l is PrivateLease)
{
PrivateLease p = (PrivateLease)l;
//do private logic here
}
else if (l if BussinessLease)
{
BussinessLease b = (BunessinessLease)l;
//do bussiness logic here
}

Categories

Resources