I'm trying to find a neat way to trigger a loading mechanism when one of several getters is first accessed. My first thoughts are about something like this:
public class Customer {
private bool loaded = false;
public int PK { get; set; }
public string Email { get; set; }
public string Name { get { if (!loaded) loadData(); return _name; } set { ... } }
public string Street { get { if (!loaded) loadData(); return _street; } set { ... } }
public string City { get { if (!loaded) loadData(); return _city; } set { ... } }
}
In short, in this example every Customer exists with its base data PK and Email until one of the other properties is accessed.
This would mean much duplicate code, increasing with the complexity of the class. Is there a way to create some kind of inheritance for these properties?
Something like this, but I don't think this is possible:
private void checkData() { if (!loaded) loadData(); }
public string Name:checkData { get; set; }
public string Street:checkData { get; set; }
public string City:checkData { get; set; }
Another way might be possible through reflection, but as I'm not experienced with it I don't know where to start here.
Any hints are deeply appreciated! ;-)
You can use the Lazy<T> class to wrap the secondary properties.
This way loadData will only execute if any of the secondary getters is called and won't be executed more than once.
public class Customer
{
public int PK { get; set; }
public string Email { get; set; }
public string Name { get { return data.Value.Name; } }
public string Street { get { return data.Value.Street; } }
public string City { get { return data.Value.City; } }
public Customer()
{
data = new Lazy<CustomerData>(loadData);
}
private CustomerData loadData()
{
...
}
private struct CustomerData
{
public string Name, Street, City;
}
private Lazy<CustomerData> data;
}
There is another, not so beautiful, way. You could write a wrapping generic method, which reduces the code inside your properties.
Here's an example:
public string Name
{
get { return Get(m_name); }
set { m_name = value; }
}
public static T Get<T>(T value)
{
if (!loaded)
{
loadData();
}
return value;
}
Please note, that this will decrease the performance, because your properties will always call an extra method. You can try to force the compiler to inline that method (if it does not happen already).
Related
I am invoking a method in my constructor like below.Is this the right way to do to set properties based on some validations.Please suggest.
public class Asset
{
public Asset(string id)
{
SetStorageId(id);
}
public string AssetId { get; set; }
public string UtilId { get; set; }
public string MappingId { get; set; }
public bool IsActive { get; set; }
private void SetStorageId(string id)
{
if (Regex.Match(id, "^[A-Z][a-zA-Z]*$").Success)
{
AssetId = id;
}
else
{
UtilId = id;
}
}
}
In my opinion your design should be like below,
You should abstract common items to base class and create specific class inheriting this,
and decide from client(consumer) which instance do you need and construct it
public class AssetBase
{
public string MappingId { get; set; }
public bool IsActive { get; set; }
}
public class Asset : AssetBase
{
public string AssetId { get; set; }
}
public class Util : AssetBase
{
public string UtilId { get; set; }
}
static void Main(string[] args)
{
string id = Console.ReadLine();
if (Regex.Match(id, "^[A-Z][a-zA-Z]*$").Success)
{
Asset asset = new Asset();
asset.AssetId = id;
}
else
{
Util util = new Util();
util.UtilId = id;
}
}
simply try this
public class Asset
{
private string id;
public string AssetId { get; set; }
public string UtilId { get; set; }
public string Id
{
set
{
if (Regex.Match(value, "^[A-Z][a-zA-Z]*$").Success)
{
this.id = value;
}
else
{
UtilId = value;
}
}
get
{
return id;
}
}
}
When you create a property in c#, a private variable is created for that property on compile time. When you try to set the Id property in the code above the Id you pass goes into the value keyword and you can perform your validations on the value keyword and set your property accordingly.
No need to complicate your code with set methods, constructors or deriving classes
or you can even use data annotations which is a more elegant way https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationattribute.aspx#Properties
using System.ComponentModel.DataAnnotations;
public class Asset
{
[RegularExpression("^[A-Z][a-zA-Z]*$")]
public string Id { get; set; }
}
It's not wrong. It can possibly grow to be a little confusing. Maybe you can make it clearer by moving the bod of SetStorageId to the constructor. Perhaps there is no need to complicate with subclassing, relative to other code within the project.
I have been given this interface to start with. There are a number of functions I must implement.
using System;
using System.Windows.Forms;
public interface IInfoCard
{
string Name { get; set; }
string Category { get; }
string GetDataAsString();
void DisplayData(Panel displayPanel);
void CloseDisplay();
bool EditData();
}
How would I implement the following function into the interface.
class Class2 : IInfoCard
{
public string Name
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
You should use then Abstract classes, not interfaces, then.
public abstract class IInfoCard
{
string Name { get; set; }
string Category { get; }
string GetDataAsString() { return null; }
void DisplayData(Panel displayPanel) {}
void CloseDisplay() {}
bool EditData() { return true;}
}
You are trying to implement a property. You can basically encapsulate a field.
An easy way to do that is using auto-property:
public string Name { get; set; }
Try this
public class Class2 : IInfoCard
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
}
You can use Auto-Implemented Properties
public class Class2 : IInfoCard
{
public string Name { get; set;}
}
See More
You have two options.
Option 1:
Make them Auto properties, in which case compiler creates a private, anonymous backing field.
public string Name {get;set};
Option 2
Defining an explicit backing field, a private field.
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
I have 2 web refs which I can't change:
They are almost identical but when referenced one only accepts ProperCase and the other Uppercamelcase.
Example
Not only props is the thing but entire classes with its props and methods
#EDIT: Sorry, I've realized it's more complicated than initially stated:
Not only props is the thing but entire classes with its props and methods and inner classes. Although only used as structures, inner classes have the same issue.
public class Foobar
{
public string Logmsgno;
public string Revno;
public string Reqsox;
public void Dosomething();
public Barbaz Mybarbaz;
public List<quux> Myquuxlist;
}
And the other has names like
public class FooBar
{
public string LogMsgNo;
public string RevNo;
public string ReqSox;
public void DoSomething();
public BarBaz MyBarBaz;
public List<Quux> MyQuuxList;
}
Is there an easy way to make an interface for both?
TIA!
Without a proper re-factoring to update everything and changing names, yes, you COULD with a little bit of smoke and mirrors. Create an interface based on the NEW values you WANT them to be, then change them to respectively use getter/setter to retain original and not break it.
To expand from your expanded question. You would have to adjust each of those levels too.. Define an interface for the "Barbaz" and "BarBaz" class so your outer class can have an object of
public interface IYourBarBazInterface
{
string BarBazProp1 { get; set; }
string AnotherProp { get; set; }
}
public interface IQuux
{
int QuuxProp { get; set; }
string AnotherQuuxProp { get; set; }
}
public interface IYourCommonInterface
{
string LogMsgNo { get; set; };
string RevNo { get; set; };
string ReqSox { get; set; };
// Similar principle of declarations, but interface typed objects
IYourBarBazInterface MyBarBaz { get; set; }
List<IQuux> MyQuuxList;
void DoSomething();
}
public class Foobar : IYourCommonInterface
{
public string Logmsgno;
public string Revno;
public string Reqsox;
public void Dosomething();
// your existing old versions keep same name context
// but showing each of their respective common "interfaces"
public IYourBarBazInterface mybarbaz;
public List<IQuux> myQuuxlist = new List<IQuux>();
// these are the implementations of the interface...
public string LogMsgNo
{ get { return Logmsgno; }
set { Logmsgno = value; }
}
public string RevNo
{ get { return Revno; }
set { Revno = value; }
}
public string ReqSox
{ get { return Reqsox; }
set { Reqsox = value; }
}
public void DoSomething()
{ Dosomething(); }
// Now, the publicly common Interface of the "IYourCommonInterface"
// that identify the common elements by common naming constructs.
// similar in your second class.
public IYourBarBazInterface MyBarBaz
{ get { return mybarbaz; }
set { mybarbaz = value; }
}
public List<IQuux> MyQuuxList
{ get { return myQuuxlist; }
set { myQuuxlist = value; }
}
}
public class FooBar : IYourCommonInterface
{
// since THIS version has the proper naming constructs you want,
// change the original properties to lower case start character
// so the interface required getter/setter will be properly qualified
public string logMsgNo;
public string revNo;
public string reqSox;
public IYourBarBazInterface MyBarbaz;
public List<IQuux> Myquuxlist;
// these are the implementations of the interface...
public string LogMsgNo
{ get { return logMsgMo; }
set { logMsgNo = value; }
}
public string RevNo
{ get { return revNo; }
set { revNo = value; }
}
public string ReqSox
{ get { return reqSox; }
set { reqSox = value; }
}
// Since your "DoSomething()" method was already proper case-sensitive
// format, you can just leave THIS version alone
public void DoSomething()
{ .. do whatever .. }
public IYourBarBazInterface MyBarBaz
{ get { return MyBarbaz; }
set { MyBarbaz = value; }
}
public List<IQuux> MyQuuxList
{ get { return myquuxlist; }
set { myquuxlist = value; }
}
}
Unfortunately, no. There's not. C# is case sensitive (including interfaces). To have them both conform to a single interface, the name case would have to match. If you did that, the classes would be the same anyway.
Your only option would be to create an interface that used one of the casing methods, implement it on both classes, and then add code to one class (with the naming convention you didn't chose) to pass through the calls:
public interface IFooBar
{
string LogMsgNo { get; set; }
string RevNo { get; set; }
string ReqSox { get; set; }
void DoSomething();
}
public class Foobar : IFooBar
{
public string Logmsgno;
public string Revno;
public string Reqsox;
public void Dosomething();
public string LogMsgNo
{
get { return Logmsgno; }
set { Logmsgno = value; }
}
// And so on
}
UPDATE
After seeing your edit, things become much more complex. You'll have to do the same thing to all of the inner classes and then have your interfaces reference the lower level interfaces. Same concept, just more work.
If I had to handle this, I would likely write an extension method to convert from one type to another. Some reflection would do most of the work. new Foobar().ToFooBar().ToFoobar() Or write a class I would always interact with and at the last point you need to access the right implementation, call the ToFoobar().
I have two functions that do the basically same thing on two different classes.... each class has different properties.
For example:
public class ClassA
{
public int ColorID {get;set;}
public string ColorDescription {get;set;}
}
public class ClassB
{
public int TypeID {get;set;}
public string TypeDescription {get;set;}
}
public void ExFunctionSaveA(ClassA aClass)
{
aClass.ColorID=1;
aClass.ColorDescription="My Color";
Save();
}
public void ExFunctionSaveB(ClassB bClass)
{
bClass.TypeID=2;
bClass.TypeDescription="My Type";
Save();
}
As you can see the classes and the functions have the same type structure, just the property names are different... but I feel like I am repeating code doing this
Is there a way to make ExFunctionA and ExFunctionB into one function, so that I could use this for all classes that have similar structure
I know I could do some sort of generic thing like
public void ExFunctionSave<T>() // T is either ClassA or ClassB
{
.
.
.
.
Save();
}
but how would I handle the properties of each
Rather than using a generic, why not use inheritance to solve this?
public class theBase
{
string ID;
string Description;
}
public class theColor : theBase
{
}
public class theType : theBase
{
}
public void ExFunctionSaveA(theBase base)
{
base.ID=1;
base.Description="My Color";
Save();
}
If you can alter the definitions of your classes, then the best approach would be to make them implement a common interface that contains the properties you want to access:
public interface IDescribable
{
int ID { get; set; }
string Description { get; set; }
}
public class ClassA
{
public int ID { get; set; }
public string Description { get; set; }
public int ColorID
{
get { return ID; }
set { ID = value; }
}
public string ColorDescription
{
get { return Description; }
set { Description = value; }
}
}
public class ClassB
{
public int ID { get; set; }
public string Description { get; set; }
public int TypeID
{
get { return ID; }
set { ID = value; }
}
public string TypeDescription
{
get { return Description; }
set { Description = value; }
}
}
public void ExFunctionSave(IDescribable d, int id, string desc)
{
d.ID = id;
d.Description = desc;
Save();
}
Nothing more you can do unless the the 2 classes implement the same interface which has the function. In your case, even the function signatures are different.
You could define an Interface with attributes id and description.
The clases that has this structure could implement that interface.
And your method receive as parameter the interface and execute the moethods ...
Take a look at Reflection.
Reflection will let your code receive a ClassA, and discover that it has a ColourID and a ColorDescription. Likewise, when you receive a ClassB, you can discover its TypeID and TypeDescription. It's cool.
I would probably recommend a common interface, at least for your example, but if you're trying to something more complex and more generic, Reflection is the way to go.
At the moment I'm doing something like:
public virtual String zipcodeRaw { get; set; }
public virtual String zipcode {
get
{
return zipcodeRaw.Trim();
}
}
Is there a way I can do something like:
public virtual String zipcode {
get
{
return zipcode.Trim();
}
}
That would give you an infinite loop since zipcode refers to itself. However, properties are just public accessors and modifiers for a private variable. You could certainly do:
private string _zipcode;
public virtual string zipcode {
get { return _zipcode.Trim(); }
}