I've got a base class called DAL_Base for a large project that does most of the SQL lifting.
DAL_Base has fields for SELECT statements, a GetRecords() method, and a virtual FillData(IDataRecord).
public class DAL_Base<T> where T : IDisposable, new() {
private string connStr;
public DAL_Base() {
connStr = ConfigurationManager.ConnectionStrings["CompanyDatabaseConnStr"].ConnectionString;
}
internal string SP_GET { get; set; }
internal SqlConnection m_openConn {
get {
var obj = new SqlConnection(connStr);
obj.Open();
return obj;
}
}
internal virtual T FillDataRecord(IDataRecord record) {
return new T();
}
internal TList<T> Get() {
if (String.IsNullOrEmpty(SP_GET)) {
throw new NotSupportedException(string.Format("Get Procedure does not exist for {0}.", typeof(T)));
}
var list = new TList<T>();
using (var cmd = new SqlCommand(SP_GET, m_openConn)) {
cmd.CommandType = cmd.GetCommandTextType();
using (var r = cmd.ExecuteReader()) {
while (r.Read()) {
list.Add(FillDataRecord(r));
}
}
cmd.Connection.Close();
}
return list;
}
}
There is a lot more, but this should suffice for a single example.
TList is just a List<T> class:
internal class TList<T> : List<T> {
public TList() { }
}
When one of my classes inherits from it, I wanted it to be able to override the base class's FillDataRecord(IDataRecord).
For example, EmployeeDB ** inherits **DAL_BASE.
When I call EmployeeDB.GetEmployeeList(), it uses DAL_BASE to pull the records:
public class EmployeeDB : DAL_Base<Employee> {
private static EmployeeDB one;
static EmployeeDB() {
one = new EmployeeDB() {
SP_GET = "getEmployeeList",
};
}
private EmployeeDB() { }
internal override Employee FillDataRecord(IDataRecord record) {
var item = base.FillDataRecord(record);
item.Emp_Login = record.Str("Emp_Login");
item.Emp_Name = record.Str("Emp_Name");
item.Emp_Email = record.Str("Emp_Email");
item.Emp_Phone = record.Str("Emp_Phone");
item.Emp_Role = record.Str("Emp_Role");
return item;
}
public static EmployeeList GetEmployeeList() {
var list = new EmployeeList();
list.AddRange(one.Get());
return list;
}
}
In the code above, when GetEmployeeList() calls the DAL_Base method Get(), only DAL_Base::FillDataRecord(IDataRecord) is called.
I really need EmployeeDB::FillDataRecord(IDataRecord) to be called, but I can't make DAL_Base::FillDataRecord(IDataRecord) abstract.
What is the way around this?
All I know of right now is to create an EventHandler, which is what I just thought of, so I'm going to work towards that.
If anyone knows of a better route, please chime in!
One solution is to pass a delegate for Derived.FillDataRecord to the base class via the constructor.
public class DAL_Base<T> where T : IDisposable, new() {
private string connStr;
public DAL_Base() {
connStr = ConfigurationManager.ConnectionStrings["CompanyDatabaseConnStr"].ConnectionString;
}
private Func<IDataRecord, T> _fillFunc;
public DAL_Base(Func<IDataRecord, T> fillFunc) : this() {
_fillFunc = fillFunc;
}
// ...
internal TList<T> Get() {
if (String.IsNullOrEmpty(SP_GET)) {
throw new NotSupportedException(string.Format("Get Procedure does not exist for {0}.", typeof(T)));
}
var list = new TList<T>();
using (var cmd = new SqlCommand(SP_GET, m_openConn)) {
cmd.CommandType = cmd.GetCommandTextType();
using (var r = cmd.ExecuteReader()) {
while (r.Read()) {
list.Add(_fullFunc(r));
}
and in the derived class:
public class EmployeeDB : DAL_Base<Employee> {
public EmployeeDB() : base(r => FillDataRecord(r)) { }
private Employee FillDataRecord(IDataRecord record) {
var item = base.FillDataRecord(record);
item.Emp_Login = record.Str("Emp_Login");
item.Emp_Name = record.Str("Emp_Name");
item.Emp_Email = record.Str("Emp_Email");
item.Emp_Phone = record.Str("Emp_Phone");
item.Emp_Role = record.Str("Emp_Role");
return item;
}
}
Related
I'm developing a library for developers where they have to create a class that inherits from a class I created.
This base class essentially manages an array of objects for the developer, however the developer gets to specify the type of these objects they want the base class to manage.
So the developer essentially just tells the base class to create an array, then only has read only access to that array. The base class will (depending on the state of the application) add or remove objects from the array.
I'm stuck at finding the right data type to store such a thing. I've tried ref and out but that got me nowhere. The closest I got was with a Dictionary but that idea fell apart because C# is actually just copying the value into the dictionary instead of referencing or pointing to it.
Here is a quick example I threw together:
public static void Main()
{
Derived d = new Derived();
d.InitBase();
d.Init();
d.CheckArray();
d.AddElement<GenericObject>(new GenericObject{ i = 2 });
d.CheckArray();
}
public class Base {
Dictionary<Type, List<object>> ArrayReferences;
public void InitBase() {
ArrayReferences = new Dictionary<Type, List<object>>();
}
protected ReadOnlyCollection<T> RegisterArray<T>() {
List<object> managedArray = new List<object>();
ArrayReferences.Add(typeof(T), managedArray);
return Array.AsReadOnly(managedArray.Select(s => (T)s).ToArray());
}
public void AddElement<T>(T obj) {
ArrayReferences[typeof(T)].Add(obj);
}
public void RemoveElement<T>(T obj) {
ArrayReferences[typeof(T)].Remove(obj);
}
}
public class Derived: Base {
ReadOnlyCollection<GenericObject> arr;
public void Init() {
arr = RegisterArray<GenericObject>();
}
public void CheckArray() {
Console.WriteLine(arr.Count());
}
}
public class GenericObject {
public int i = 0;
}
Output:
0
0
Dictionary obviously doesn't store the values as references like I want it to. So what other technique does C# have or is this simply not possible? Also not sure how many issues unsafe will cause me so I'm scared going that route.
While I think there are better ways of handling this issue, this can be done.
Instead of storing a List<object> reference, which isn't compatible with a List<T>, store an object. Use a static in Base to hold the Dictionary so there is one Dictionary for all derived classes.
public static void Main() {
var d = new Derived();
d.CheckCollection("d before AddElement");
d.AddElement(new GenericObject { i = 2 });
d.CheckCollection("d after AddElement");
Console.WriteLine($"ListCount = {Base.ListCount}");
var d2 = new Derived2();
d2.CheckCollection("d2 before AddElement");
d2.AddElement(new GenericObject2 { i = 4 });
d2.AddElement(new GenericObject2 { i = 5 });
d2.CheckCollection("d2 after AddElement");
Console.WriteLine($"ListCount = {Base.ListCount}");
}
public class Base {
static Dictionary<Type, object> ListReferences = new Dictionary<Type, object>();
public static int ListCount => ListReferences.Count();
protected ReadOnlyCollection<T> RegisterList<T>() {
var managedList = new List<T>();
ListReferences.Add(typeof(T), managedList);
return managedList.AsReadOnly();
}
public void AddElement<T>(T obj) {
((List<T>)ListReferences[typeof(T)]).Add(obj);
}
public void RemoveElement<T>(T obj) {
((List<T>)ListReferences[typeof(T)]).Remove(obj);
}
}
public class Derived : Base {
ReadOnlyCollection<GenericObject> roc;
public Derived() {
roc = RegisterList<GenericObject>();
}
public void CheckCollection(string msg) {
Console.WriteLine(msg);
Console.WriteLine(roc.Count());
}
}
public class Derived2 : Base {
ReadOnlyCollection<GenericObject2> roc;
public Derived2() {
roc = RegisterList<GenericObject2>();
}
public void CheckCollection(string msg) {
Console.WriteLine(msg);
Console.WriteLine(roc.Count());
}
}
public class GenericObject {
public int i = 0;
}
public class GenericObject2 {
public int i = 0;
}
PS Also, don't name methods and variables with "array" when you are using Lists.
The following code you've written makes a copy of your list at the time you created it - so it is always empty, no matter what you add to the list afterwards.
List<object> managedArray = new List<object>();
ArrayReferences.Add(typeof(T), managedArray);
return Array.AsReadOnly(managedArray.Select(s => (T)s).ToArray());
Here is how you should write your code to get what you want:
public static void Main()
{
Derived d = new Derived();
Console.WriteLine(d.AsReadOnly().Count);
d.AddElement(new GenericObject { i = 2 });
Console.WriteLine(d.AsReadOnly().Count);
}
public class Base<T>
{
List<T> _items = new List<T>();
public ReadOnlyCollection<T> AsReadOnly()
{
return Array.AsReadOnly(_items.ToArray());
}
public void AddElement(T obj)
{
_items.Add(obj);
}
public void RemoveElement(T obj)
{
_items.Remove(obj);
}
}
public class Derived : Base<GenericObject>
{
}
public class GenericObject
{
public int i = 0;
}
That outputs:
0
1
Now, it's worth considering that List<T> already has a AsReadOnly() method, so you could simply write this:
public static void Main()
{
var d = new List<GenericObject>();
Console.WriteLine(d.AsReadOnly().Count);
d.Add(new GenericObject { i = 2 });
Console.WriteLine(d.AsReadOnly().Count);
}
public class GenericObject
{
public int i = 0;
}
That works too.
Here's how you should do this to hold more than one list at a time. There's no need for inheritance.
public static void Main()
{
Repository r = new Repository();
Console.WriteLine(r.AsReadOnly<GenericObject>().Count);
r.AddElement<GenericObject>(new GenericObject { i = 2 });
Console.WriteLine(r.AsReadOnly<GenericObject>().Count);
}
public class Repository
{
private Dictionary<Type, object> _references = new Dictionary<Type, object>();
private void Ensure<T>()
{
if (!_references.ContainsKey(typeof(T)))
{
_references[typeof(T)] = new List<T>();
}
}
public ReadOnlyCollection<T> AsReadOnly<T>()
{
this.Ensure<T>();
return (_references[typeof(T)] as List<T>).AsReadOnly();
}
public void AddElement<T>(T obj)
{
this.Ensure<T>();
(_references[typeof(T)] as List<T>).Add(obj);
}
public void RemoveElement<T>(T obj)
{
this.Ensure<T>();
(_references[typeof(T)] as List<T>).Remove(obj);
}
}
public class GenericObject
{
public int i = 0;
}
In your base (or encapsulated class if you choose to go that way):
protected ReadOnlyCollection<T> GetSnapshot<T>() {
return Array.AsReadOnly(ArrayReferences[typeof(T)].Select(s => (T)s).ToArray());
}
Then you'd also add any other methods to view the data, e.g. to get a count:
protected int GetCount<T>() {
return ArrayReferences[typeof(T)].Count;
}
I need the separate classes for Xml Serialization. I'd like to know if there is a simpler way for the inheriting BuildingDetail class to acquire the property values from the parent Building class.
Parent Class
public class Building
{
public int BuildingId;
public string BuildingName;
protected Building()
{
}
private Building(int buildingId, string buildingName)
{
BuildingId = buildingId;
BuildingName = buildingName;
}
public static Building Load(int buildingId)
{
var dr = //DataRow from Database
var building = new Building(
(int) dr["BuildingId"],
(string) dr["BuildingName"]);
return building;
}
}
Inheriting Class
public class BuildingDetail : Building
{
public BaseList<Room> RoomList
{
get { return Room.LoadList(BuildingId); }
}
protected BuildingDetail()
{
}
// Is there a cleaner way to do this?
private BuildingDetail(int buildingId, string buildingName)
{
BuildingId = buildingId;
BuildingName = buildingName;
}
public new static BuildingDetail Load(int buildingId)
{
var building = Building.Load(buildingId);
var buildingDetail = new BuildingDetail(
building.BuildingId,
building.BuildingName
);
return buildingDetail;
}
}
Thanks.
Firstly, change your base class constructor access modifier to protected. And then you can call base class constructor with base keyword:
private BuildingDetail(int buildingId, string buildingName)
: base(buildingId, buildingName)
{
...
}
It will call the base constructor first. Also if you don't put the :base(param1, param2) after your constructor, the base's empty constructor will be called.
I came across this recently while writing the code. Is there a way we can write a code in base class so it identifies the correct extension method based on the type?
namespace GenericsInheritance
{
public class Animal { }
public class Dinasaur : Animal { }
public class Dragon : Animal { }
public abstract class Zoo<T> where T : Animal
{
public virtual string IdentifyYourSelf(T record)
{
//Calling extension method
string name = record.IdentifyYourSelf();
return name;
}
}
public class DinasaurZoo : Zoo<Dinasaur>
{
//I could use this, just wanted to try if base class method does identify the correct extension method for the type.
//public override string IdentifyYourSelf(Dinasaur record)
//{
// return record.IdentifyYourSelf();
//}
}
public class DragonZoo : Zoo<Dragon> { }
public class AnimalZoo : Zoo<Animal> { }
//Extensions methods class.
public static class LieDetector
{
public static string IdentifyYourSelf(this Animal record) { return "Animal"; }
public static string IdentifyYourSelf(this Dinasaur record) { return "Dinasaur"; }
public static string IdentifyYourSelf(this Dragon dog) { return "Dragon"; }
//It works if I use this.
//public static string IdentifyYourSelf<T>(this T record) where T : Animal
//{
// if (record is Dinasaur) { var dinasaur = record as Dinasaur; return IdentifyYourSelf(dinasaur); }
// else if (record is Dragon) { var dragon = record as Dragon; return IdentifyYourSelf(dragon); }
// else return "I do not exist";
//}
}
public class FbiInterrogation
{
public static void Main(string[] args)
{
var animal = new Animal();
var dinasaur = new Dinasaur();
var dragon = new Dragon();
var dinasaurZoo = new DinasaurZoo();
var dragonZoo = new DragonZoo();
var animalZoo = new AnimalZoo();
string name = dinasaurZoo.IdentifyYourSelf(dinasaur); //Prints Animal expecting Dinasaur
name = dragonZoo.IdentifyYourSelf(dragon); //Prints Animal expecting Dragon
name = animalZoo.IdentifyYourSelf(animal); //Prints Animal
Console.ReadKey();
}
}
}
Extension methods are resolved according to the static type of the variable on which they're called, not the run-time type. So the answer to your question is "no" -- you have to do it via an override in the derived class, or by cumbersome type checking, as you indicate in your question.
This could actually be achieved using reflection, though I'm not sure if it's the best idea to do so:
public abstract class Zoo<T> where T : Animal
{
public virtual string IdentifyYourSelf(T record)
{
return typeof(LieDetector).GetMethod("IdentifyYourSelf", new[] {typeof(T)}, null).Invoke(record, new object[] {record}) as string;
}
}
Let's assume I have a class like
public class DataService
{
public IList<T> All<T>() { ... }
public T Get<T>(int id) { ... }
...
}
I could use it in various ways...
var dataService = new DataService();
var customers = dataService.All<Customer>();
var order = dataService.Get<Order>(1);
... but if I had a bunch of operations with the same T, this would become cumbersome. Then it would be nice to have something like this:
dataService.TypeIs<Order>();
var order2 = dataService.Get(2);
var order2 = dataService.Get(3);
var allOrders = dataService.All();
How would a TypeIs<T>() method look like? I think it had to somehow convert DataService to DataService<T> and set T... Or is this utterly impossible?
Yes, it's possible using a clever proxy:
public class DataService
{
public IList<T> All<T>() { ... }
public T Get<T>(int id) { ... }
...
}
public class DataServiceProxy<T>
{
public DataServiceProxy(DataService ds)
{
this.ds = ds;
}
public IList<T> All()
{
return this.ds.All<T>();
}
public T Get(int id)
{
return this.ds.Get<T>(id);
}
}
The equivalent of your dataService.TypeIs<Order>(); is var dataServiceProxy = new DataServiceProxy<Order>(dataService).
I have an abstract base class Base which has some common properties, and many derived ones which implement different logic but rarely have additional fields.
public abstract Base
{
protected int field1;
protected int field2;
....
protected Base() { ... }
}
Sometimes I need to clone the derived class. So my guess was, just make a virtual Clone method in my base class and only override it in derived classes that have additional fields, but of course my Base class wouldn't be abstract anymore (which isn't a problem since it only has a protected constructor).
public Base
{
protected int field1;
protected int field2;
....
protected Base() { ... }
public virtual Base Clone() { return new Base(); }
}
public A : Base { }
public B : Base { }
The thing is, since I can't know the type of the derived class in my Base one, wouldn't this lead to have a Base class instance even if I call it on the derived ones ? (a.Clone();) (actually after a test this is what is happening but perhaps my test wasn't well designed that's why I have a doubt about it)
Is there a good way (pattern) to implement a base Clone method that would work as I expect it or do I have to write the same code in every derived class (I'd really like to avoid that...)
Thanks for your help
You can add a copy constructor to your base class:
public abstract Base
{
protected int field1;
protected int field2;
protected Base() { ... }
protected Base(Base copyThis) : this()
{
this.field1 = copyThis.field1;
this.field2 = copyThis.field2;
}
public abstract Base Clone();
}
public Child1 : Base
{
protected int field3;
public Child1 () : base() { ... }
protected Child1 (Child1 copyThis) : base(copyThis)
{
this.field3 = copyThis.field3;
}
public override Base Clone() { return new Child1(this); }
}
public Child2 : Base
{
public Child2 () : base() { ... }
protected Child (Child copyThis) : base(copyThis)
{ }
public override Base Clone() { return new Child2(this); }
}
public Child3 : Base
{
protected int field4;
public Child3 () : base() { ... }
protected Child3 (Child3 copyThis) : base(copyThis)
{
this.field4 = copyThis.field4;
}
public override Base Clone()
{
var result = new Child1(this);
result.field1 = result.field2 - result.field1;
}
}
Just override the Clone and have another method to CreateInstance then do your stuff.
This way you could have only Base class avoiding generics.
public Base
{
protected int field1;
protected int field2;
....
protected Base() { ... }
public virtual Base Clone()
{
var bc = CreateInstanceForClone();
bc.field1 = 1;
bc.field2 = 2;
return bc;
}
protected virtual Base CreateInstanceForClone()
{
return new Base();
}
}
public A : Base
{
protected int fieldInA;
public override Base Clone()
{
var a = (A)base.Clone();
a.fieldInA =5;
return a;
}
protected override Base CreateInstanceForClone()
{
return new A();
}
}
I did something similar as Alexander Simonov, but perhaps simpler. The idea is (as I said in a comment) to have just one Clone() in the base class and leave all the work to a virtual CloneImpl() which each class defines as needed, relying on the CloneImpl()s of the base classes.
Creation of the proper type is left to C#'s MemberwiseClone() which will do whatever it takes for the object that's calling. This also obviates the need for a default constructor in any of the classes (none is ever called).
using System;
namespace CloneImplDemo
{
// dummy data class
class DeepDataT : ICloneable
{
public int i;
public object Clone() { return MemberwiseClone(); }
}
class Base: ICloneable
{
protected virtual Base CloneImpl()
{
// Neat: Creates the type of whatever object is calling.
// Also obviates the need for default constructors
// (Neither Derived1T nor Derived2T have one.)
return (Base)MemberwiseClone();
}
public object Clone()
{
// Calls whatever CloneImpl the
// actual calling type implements.
return CloneImpl();
}
}
// Note: No Clone() re-implementation
class Derived1T : Base
{
public Derived1T(int i) { der1Data.i = i; }
public DeepDataT der1Data = new DeepDataT();
protected override Base CloneImpl()
{
Derived1T cloned = (Derived1T)base.CloneImpl();
cloned.der1Data = (DeepDataT)der1Data.Clone();
return cloned;
}
}
// Note: No Clone() re-implementation.
class Derived2T : Derived1T
{
public Derived2T(int i1, int i2) : base(i1)
{
der2Data.i = i2;
}
public string txt = string.Empty; // copied by MemberwiseClone()
public DeepDataT der2Data = new DeepDataT();
protected override Base CloneImpl()
{
Derived2T cloned = (Derived2T)base.CloneImpl();
// base members have been taken care of in the base impl.
// we only add our own stuff.
cloned.der2Data = (DeepDataT)der2Data.Clone();
return cloned;
}
}
class Program
{
static void Main(string[] args)
{
var obj1 = new Derived2T(1,2);
obj1.txt = "this is obj1";
var obj2 = (Derived2T)obj1.Clone();
obj2.der1Data.i++;
obj2.der2Data.i++; // changes value.
obj2.txt = "this is a deep copy"; // replaces reference.
// the values for i should differ because
// we performed a deep copy of the DeepDataT members.
Console.WriteLine("obj1 txt, i1, i2: " + obj1.txt + ", " + obj1.der1Data.i + ", " + obj1.der2Data.i);
Console.WriteLine("obj2 txt, i1, i2: " + obj2.txt + ", " + obj2.der1Data.i + ", " + obj2.der2Data.i);
}
}
}
Output:
obj1 txt, i1, i2: this is obj1, 1, 2
obj2 txt, i1, i2: this is a deep copy, 2, 3
You could do something like this:
public class Base<T> where T: Base<T>, new()
{
public virtual T Clone()
{
T copy = new T();
copy.Id = this.Id;
return copy;
}
public string Id { get; set; }
}
public class A : Base<A>
{
public override A Clone()
{
A copy = base.Clone();
copy.Name = this.Name;
return copy;
}
public string Name { get; set; }
}
private void Test()
{
A a = new A();
A aCopy = a.Clone();
}
But i doubt that it will bring something useful. I'll create another example..
I got another idea using the Activator class:
public class Base
{
public virtual object Clone()
{
Base copy = (Base)Activator.CreateInstance(this.GetType());
copy.Id = this.Id;
return copy;
}
public string Id { get; set; }
}
public class A : Base
{
public override object Clone()
{
A copy = (A)base.Clone();
copy.Name = this.Name;
return copy;
}
public string Name { get; set; }
}
A a = new A();
A aCopy = (A)a.Clone();
But i would go for the Alexander Simonov answer.
If performance is not important for your case, you can simplify your code by creating just one general clone method which can clone whatever to whatever if properties are same:
Base base = new Base(){...};
Derived derived = XmlClone.CloneToDerived<Base, Derived>(base);
public static class XmlClone
{
public static D CloneToDerived<T, D>(T pattern)
where T : class
{
using (var ms = new MemoryStream())
{
using (XmlWriter writer = XmlWriter.Create(ms))
{
Type typePattern = typeof(T);
Type typeTarget = typeof(D);
XmlSerializer xmlSerializerIn = new XmlSerializer(typePattern);
xmlSerializerIn.Serialize(writer, pattern);
ms.Position = 0;
XmlSerializer xmlSerializerOut = new XmlSerializer(typeTarget, new XmlRootAttribute(typePattern.Name));
D copy = (D)xmlSerializerOut.Deserialize(ms);
return copy;
}
}
}
}
Found this question while trying to solve this exact problem, had some fun with LINQPad while at it.
Proof of concept:
void Main()
{
Person p = new Person() { Name = "Person Name", Dates = new List<System.DateTime>() { DateTime.Now } };
new Manager()
{
Subordinates = 5
}.Apply(p).Dump();
}
public static class Ext
{
public static TResult Apply<TResult, TSource>(this TResult result, TSource source) where TResult: TSource
{
var props = typeof(TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var p in props)
{
p.SetValue(result, p.GetValue(source));
}
return result;
}
}
class Person
{
public string Name { get; set; }
public List<DateTime> Dates { get; set; }
}
class Manager : Person
{
public int Subordinates { get; set; }
}