Extending using C# generics? - c#

I want to create an extendable nested structure and it seems like I should be able to do this using generics, though I may not be using them "properly".
I want to be able to create child classes from GroupType and/or OptionType. The problem is that I can't perform the new operation on the generic types even though I specified they could only be of a certain base type.
Is there any way to do what I'm trying to do?
public class AllInfo<GroupType, OptionType>
where GroupType: GroupBase<OptionType>
where OptionType: OptionBase
{
public List<string> Names { set; get; }
public List<GroupType> Groups { set; get; }
public AllInfo()
{
DataSet ds = DatabaseRetreival();
this.Groups.add(new GroupType(ds["Name"], ds["Type"]));
}
}
public class GroupBase<OptionType>
where OptionType: OptionBase
{
public string Name { set; get; }
public string Type { set; get; }
public List<OptionType> Options { set; get; }
public GroupBase(string name, string type)
{
this.Name = name;
this.Type = type;
DataSet ds = DatabaseRetreival(this.Type);
this.Options.Add(new OptionType(ds["Name"]));
}
}
public class OptionBase
{
public string Name { set; get; }
public OptionBase(string name)
{
this.Name = name;
}
}

You have to specify the classes must have a default constructor.
where GroupType: GroupBase<OptionType>, new()
View this article and jump down to the section titled Generic Constraints.

You can't specify which constructors a generic class should have. The constructors are not inherited, so even if the base class that you specified has that constructor, a class that derives from it doesn't have to have that constructor.
The only constructor that you can require is the parameterless constructor:
where GroupType: GroupBase<OptionType>, new()
As that only let's you use the parameterless constructor, you would also use a virtual method for putting the data in the object, for example:
GroupType group = new GroupType();
group.Init(ds["Name"], ds["Type"]);
this.Groups.add(group);

The compiler cannot allow that, because it cannot guarantee that the OptionType has a constructor with the right signature. But you can pass a factory function instead of invoking the constructor directly:
public class Foo<T>
{
private List<T> myObjects;
public Foo(Func<string, T> factory))
{
myObjects = new List<T>();
foreach (string s in GetDataStrings())
myObjects.Add(factory(s));
}
}
So if you have a Bar class with a constructor taking a string, you do this:
Func<string,Bar> barFactory = x => new Bar(x);
var foo = new Foo<Bar>(barFactory);

The problem you have is foundationally based in very high amounts of class coupling that you are trying to mitigate with inheritance/generics. I suggest you re-examine why you feel this is necessary. This quest will eventually lead you to interfaces, service-based programming, and IoCs like Ninject or Castle Windsor.
However, if you want a quick fix that further increases code complexity (because you don't have non-complex options here aside from changing your coding philosophy), use an abstract/virtual method, maybe call it Bind(), instead of constructors.
[bolded for tl;dr]

Related

Initialise one object from another where they share a common interface c#

I want to pass in an instance of an interface to an object and initialise all the values of this object to those of the object passed in where both objects implement the same interface? Are there any good shortcuts in this particular case where they share an interface. It seems to me there must be... I just can't recall ...
EDIT: After John's feedback, the question is better expressed as - How do I pass in an instance of an interface to an object's constructor and initialise all the values of this object to those of the interface instance passed in?
Most deep copying solutions (including my own previous solutions) return an object - which is not going to work in a constructor, or rely upon creating a new instance (which is not going to work with an interface as the source and destination).
I want to pass in both source and destination and have properties of the source copied to the destination where they are both interfaces. Is there an existing solution for this. Or do I revisit my own code and try to adapt it - my previous own solution from 2009 (with minor bug corrected in the answers) SetValue on PropertyInfo instance error "Object does not match target type" c# AND svics answer in transfering one object properties values to another one suffice for the simple cases where all properties are just values.
e.g.
public interface ISomething
{
...
}
public class A : ISomething
{
public A(ISomething input)
{
// what goes here??
}
}
I'm not really sure I fully understand your restrictions, but for most object copying work I use AutoMapper, which greatly helps with the grunt work of copying objects. It means a different approach than copying properties in constructors, but maybe useful. Here's some example code:
public interface ISomething {
string MyProperty { get; set; }
int AnotherProperty { get; set; }
B ClassProperty { get; set; }
}
public class A : ISomething {
public string MyProperty { get; set; }
public int AnotherProperty { get; set; }
public B ClassProperty { get; set; }
}
public class B {
public string BProperty_1 { get; set; }
public int BProperty_2 { get; set; }
}
class Program {
static void Main(string[] args) {
// Configure the mapping
Mapper.Initialize(cfg => cfg.CreateMap<ISomething, ISomething>());
// Initialize first instance
var firstA = new A {
MyProperty = "Test",
AnotherProperty = 21,
ClassProperty = new B {
BProperty_1 = "B String",
BProperty_2 = 555
}
};
// Initialize second instance and perform the mapping
var secondA = Mapper.Map<ISomething>(firstA);
Here, all the properties in firstA are copied over to secondA, including the properties in ClassProperty.
The mapping configuration is performed once on startup, and uses recursion and reflection to build the mapping model. It can then be used anywhere in your code. If new properties are added to the interface, the mapping configuration stays the same.
Simply set all the properties of the interface in the constructor:
public class A : ISomething
{
public A(ISomething input)
{
A.MyProperty = input.MyProperty;
A.AnotherProperty = somethingNotFromTheInterface
}
}
This is called a copy-constructor. Wheather this actually creates a deep or a shallow copy of your existing instance depends on if it contains references to other reference-types. In this case you´d have to re-create all those instances also:
public A(ISomething input)
{
A.MyProperty = new MyType(input.MyProperty);
A.AnotherProperty = somethingNotFromTheInterface
}
Which itself assumes you hacve a copy-constructor for the type of MyProperty also.
This can become some huge task when your interface is quite big. You may consider looping all the interfaces properties with reflection in this case, or even better rethink if your interface is actually serving a single purpose and not doing too much.

Access the declaring class in a custom attribute?

I've created a custom attribute where I want to access the the declaring class of the custom attribute property.
For example:
public class Dec
{
[MyCustomAttribute]
public string Bar {get;set;}
}
Here I would like (in the the cass of MyCustomAttribute) to get the type of the declaring class (Dec).
Is this by any means possible?
EDIT: Thanks for the replies everyone. I learned something new today.
As I've written, attributes are instantiated only when you request them with type.GetCustomAttributes(), but at that time, you alread have the Type. The only thing you can do is:
[AttributeUsage(AttributeTargets.Property)]
public class MyCustomAttribute : Attribute
{
public void DoSomething(Type t)
{
}
}
public class Dec
{
[MyCustomAttribute]
public string Bar { get; set; }
}
// Start of usage example
Type type = typeof(Dec);
var attributes = type.GetCustomAttributes(true);
var myCustomAttributes = attributes.OfType<MyCustomAttribute>();
// Shorter (no need for the first var attributes line):
// var myCustomAttributes = Attribute.GetCustomAttributes(type, typeof(MyCustomAttribute), true);
foreach (MyCustomAttribute attr in myCustomAttributes)
{
attr.DoSomething(type);
}
so pass the type as a parameter.
No, it is not - except for by build-time tools like PostSharp, Roslyn, etc.
You need to find a different approach - perhaps passing a Type in as a constructor argument; or (more likely), but having whatever logic you want to be attribute-based be aware of the declaration context; i.e. assuming MyCustomAttribute has a Foo() method, make it Foo(Type declaringType) or similar.
This might also work:
class MyCustomAttribute : Attribute
{
public Type DeclaringType { get; set; }
}
public class Dec
{
[MyCustomAttribute(DeclaringType=typeof(Dec))]
public string Bar { get; set; }
}

generic variable declaration

I am not sure if this can be accomplished at all but here is my question.
Using C#, is it possible to declare a generic or non-typed variable but later in my code specify what that variable should be?
object genericObject;
if (!testFlag)
{
genericObject = new SpecificObject1();
}
if (testFlag)
{
genericObject = new SpecificObject2();
}
genericObject.FirstName = "Samuel";
genericObject.LastName = "Jackson";
I am hoping that after the "if logic" I can now call the similar methods each "specific" object had in common.
So is it possible to create some form of generic object in the beginning of my code and instantiate the specific object I want to use later?
Maybe there is a design pattern or refactoring effort that needs to be considered here as well.
If both SpecificObject1 and SpecificObject2 share similar properties, you could add an interface for them. You could then declare genericObject as the interface type and assign the concrete type later:
public interface SomeInterface
{
string FirstName { get; set; }
string LastName { get; set; }
}
public class SpecificObject1 : SomeInterface
{
// Implementation Details
}
public class SpecificObject2 : SomeInterface
{
// Other Implementation Details
}
You would then be able to use them in the following manner:
SomeInterface genericObject;
genericObject = testFlag ? new SpecificObject2() : new SpecificObject1();
I'd recommend you define a custom interface that encapsulates all the members you need to use, and implement it on both of your concrete types::
interface IMyInteface
{
string FirstName { get; set; }
string LastName { get; set; }
}
class SpecificObject1 : IMyInterface { ... }
class SpecificObject2 : IMyInterface { ... }
And then declare your variable to be an instance of that interface:
IMyInterface genericObject;
if (!testFlag)
{
genericObject = new SpecificObject1();
}
if (testFlag)
{
genericObject = new SpecificObject2();
}
genericObject.FirstName = "Samuel";
genericObject.LastName = "Jackson";
But if that's not an option, you could use dynamic, which will force any members to be evaluated at run time:
dynamic genericObject;
if (!testFlag)
{
genericObject = new SpecificObject1();
}
if (testFlag)
{
genericObject = new SpecificObject2();
}
genericObject.FirstName = "Samuel";
genericObject.LastName = "Jackson";
You need to move all of the common members to a common base class or interface, then declare the variable as that type.
If your types, you are going to assign later, are completely unrelated to each other and mainly have different set of methods to execute, dynamic could be your choice of preference in this case.
In other cases, use standard OOP techniques, like inheritance and polymorphism to achieve what you are talking about.

C# how to inherit from default constructor

I have a simple class with 2 constructors.
The first (default) constructor that takes no parameters constructs all the properties so they are not null once this object is instantiated.
the second constructor that takes an int parameter does a lot more logic, but it also need to do exactly what the default constructor does with regards to setting up the properties.
Is there away I can inherit from this default constructor so im not duplicating code?
code below...
public class AuctionVehicle
{
public tbl_Auction DB_Auction { get; set; }
public tbl_Vehicle DB_Vehicle { get; set; }
public List<String> ImageURLs { get; set; }
public List<tbl_Bid> Bids { get; set; }
public int CurrentPrice { get; set; }
#region Constructors
public AuctionVehicle()
{
DB_Auction = new tbl_Auction();
DB_Vehicle = new tbl_Vehicle();
ImageURLs = new List<string>();
ImageURLs = new List<string>();
}
public AuctionVehicle(int AuctionID)
{
// call the first constructors logic without duplication...
// more logic below...
}
}
You can do it like this:
public AuctionVehicle(int AuctionID) : this()
{
...
}
public AuctionVehicle(int AuctionID) : this()
{
// call the first constructors logic without duplication...
// more logic below...
}
Or factor it out to a private method which contains the common logic.
public AuctionVehicle(int AuctionID)
: this()// call the first constructors logic without duplication...
{
// more logic below...
}
inheritance from constructor is not allowed in c#
Reason :-
If constructor inheritance were allowed, then necessary initialization in a base class constructor might easily be omitted. This could cause serious problems which would be difficult to track down. For example, if a new version of a base class appears with a new constructor, your class would get a new constructor automatically. This could be catastrophic.

What is the best way to define a static property which is defined once per sub-class?

I wrote the following console app to test static properties:
using System;
namespace StaticPropertyTest
{
public abstract class BaseClass
{
public static int MyProperty { get; set; }
}
public class DerivedAlpha : BaseClass
{
}
public class DerivedBeta : BaseClass
{
}
class Program
{
static void Main(string[] args)
{
DerivedBeta.MyProperty = 7;
Console.WriteLine(DerivedAlpha.MyProperty); // outputs 7
}
}
}
As this console app demonstrates, the MyProperty property exists once for all instances of BaseClass. Is there a pattern to use which would allow me to define a static property which will have allocated storage for each sub-class type?
Given the above example, I would like all instances of DerivedAlpha to share the same static property, and all instances of DerivedBeta to share another instance of the static property.
Why am I trying to do this?
I am lazily initializing a collection of class property names with certain attributes (via reflection). The property names will be identical for each derived class instance, so it seems wasteful to store this in each class instance. I can't make it static in the base class, because different sub-classes will have different properties.
I don't want to replicate the code which populates the collection (via reflection) in each derived class. I know that one possible solution is to define the method to populate the collection in the base class, and call it from each derived class, but this is not the most elegant solution.
Update - Example of what I'm doing
At Jon's request, here's an example of what I'm trying to do. Basically, I can optionally decorate properties in my classes with the [SalesRelationship(SalesRelationshipRule.DoNotInclude)] attribute (there are other attributes, this is just a simplified example).
public class BaseEntity
{
// I want this property to be static but exist once per derived class.
public List<string> PropertiesWithDoNotInclude { get; set; }
public BaseEntity()
{
// Code here will populate PropertiesWithDoNotInclude with
// all properties in class marked with
// SalesRelationshipRule.DoNotInclude.
//
// I want this code to populate this property to run once per
// derived class type, and be stored statically but per class type.
}
}
public class FooEntity : BaseEntity
{
[SalesRelationship(SalesRelationshipRule.DoNotInclude)]
public int? Property_A { get; set; }
public int? Property_B { get; set; }
[SalesRelationship(SalesRelationshipRule.DoNotInclude)]
public int? Property_C { get; set; }
}
public class BarEntity : BaseEntity
{
public int? Property_D { get; set; }
[SalesRelationship(SalesRelationshipRule.DoNotInclude)]
public int? Property_E { get; set; }
public int? Property_F { get; set; }
}
Desired end result
Accessing FooEntity.PropertiesWithDoNotInclude returns a List<string> of:
{
"Property_A",
"Property_C"
}
Accessing BarEntity.PropertiesWithDoNotInclude returns a List<string> of:
{
"Property_E"
}
Two possible approaches:
Use attributes; decorate each subclass with an attribute, e.g.
[MyProperty(5)]
public class DerivedAlpha
{
}
[MyProperty(10)]
public class DerivedBeta
{
}
That only works when they're effectively constants, of course.
Use a dictionary:
var properties = new Dictionary<Type, int>
{
{ typeof(DerivedAlpha), 5) },
{ typeof(DerivedBeta), 10) },
};
EDIT: Now that we have more context, Ben's answer is a really good one, using the way that generics work in C#. It's like the dictionary example, but with laziness, thread-safety and simple global access all built in.
Jon has a good solution as usual, although I don't see what good attributes do here, since they have to be explicitly added to every subtype and they don't act like properties.
The Dictionary approach can definitely work. Here's another way to do that, which explicitly declares that there will be one variable per subclass of BaseEntity:
class FilteredProperties<T> where T : BaseEntity
{
static public List<string> Values { get; private set; }
// or static public readonly List<string> Values = new List<string>();
static FilteredProperties()
{
// logic to populate the list goes here
}
}
The drawback of this is that it's rather difficult to pair with a GetType() call such as you might use in methods of BaseEntity. A Dictionary, or wrapper thereto which implements lazy population, is better for that usage.
I just recently needed this same thing and came across this question. I think Jon's and Fried's ideas to use a Dictionary are on the right track but don't quite hit what I was looking for so I thought I'd show my own complete and very easy to extend implementation.
public class TypeStaticProperty<T>
{
T _defaultValue;
Dictionary<Type, T> _values = new Dictionary<Type, T>();
public TypeStaticProperty(T defalutValue = default)
{
_defaultValue = defalutValue;
}
public T Get(object caller)
{
lock (_values)
{
if (_values.TryGetValue(caller?.GetType(), out T val))
return val;
else
return _defaultValue;
}
}
public void Set(object caller, T val)
{
lock (_values)
_values[caller?.GetType()] = val;
}
}
And to demonstrate:
class TestBaseClass
{
static TypeStaticProperty<int> _property = new TypeStaticProperty<int>();
public int Property
{
get => _property.Get(this);
set => _property.Set(this, value);
}
}
class TestClass1 : TestBaseClass
{
}
class TestClass2 : TestBaseClass
{
}
class Program
{
static void Main(string[] args)
{
TestClass1 test1a = new TestClass1();
TestClass1 test1b = new TestClass1();
test1a.Property = 1;
test1b.Property = 2;
TestClass2 test2a = new TestClass2();
TestClass2 test2b = new TestClass2();
test2a.Property = 3;
test2b.Property = 4;
Console.WriteLine($"test1a.Property = {test1a.Property}");
Console.WriteLine($"test1b.Property = {test1b.Property}");
Console.WriteLine($"test2a.Property = {test2a.Property}");
Console.WriteLine($"test2b.Property = {test2b.Property}");
}
}
Output:
test1a.Property = 2
test1b.Property = 2
test2a.Property = 4
test2b.Property = 4
So while you still need a class instance to access and set the property, the value will always be the same across all instances of that precise type. (This includes generics too; Foo<int> will be seen as a different type than Foo<string>). This has the huge advantage over Fried's example in that you don't need to know at compile time the precise type whose "static" value you're looking for when accessing or setting.
PS - For full disclosure, this was heavily inspired by the WPF source code, which uses a very similar pattern for DependencyProperty's and all kinds of other internal bells and whistles designed to improve performance and reduce memory footprint.

Categories