add generics on an interface property only and not on the interface - c#

i created an interface which will serve as a datatype for some set of objects, when defining those object the datatype of one of their properties are unknown, thus why i need an interface. but .net wouldnt let me do this;
public interface IClipbaseData
{
T ClipObjectData<T> { get; set;}
}
class ClipTextData : IClipbaseData
{
string _clipContent;
public string ClipObjectData
{
get
{
return _clipContent;
}
set
{
// validate the input
if (string.IsNullOrEmpty(value))
{
throw new ArgumentNullException("Error");
}
_clipContent = value;
}
}
}
i am getting an error on the interface, unexpected use of generic name. i know i could declare the generic on the interface but i dont want to because i am not aware of the generic datatype when using the interface as an object type.
but i am aware of the property datatype when creating classes to implement this interface
i can as well declare the property as object in the interface and dont use generics, but why am i unable to use generics
a typical scenario why i dont want to add the generics on the interface:
an object is defined of IClipbaseData, this object can be of any concrete class that implements IClipbaseData. the concrete class which it belongs to can only be determined at runtime, thus we dont know the datatype of the property ClipObjectData before runtime

Properties can't accept type parameters like that, you can define the type parameter on the interface itself, which will make your type work. This is one case where if you want to use a generic type parameter for a property, you must define it on the interface itself.
public interface IClipbaseData<T>
{
T ClipObjectData { get; set; }
}
class ClipTextData : IClipbaseData<string>
{
string _clipContent;
public string ClipObjectData
{
get
{
return _clipContent;
}
set
{
// validate the input
if (string.IsNullOrEmpty(value))
{
throw new ArgumentNullException("Error");
}
_clipContent = value;
}
}
}
Otherwise you would have to call properties like var someValue = clipTextDataObj.ClipObjectData<string>;, which really doesn't make a lot of sense to do it that way since the concrete type already defines what it returns.
If you do not want to define it on your interface, you'll have to create separate getter/setter methods:
public interface IClipbaseData
{
T GetClipObjectData<T>();
void SetClipObjectData<T>(T value);
}
But this would require you to implement it in a generic way:
class ClipTextData : IClipbaseData
{
public T GetClipObjectData<T>()
{
throw new NotImplementedException();
}
public void SetClipObjectData<T>(T value)
{
throw new NotImplementedException();
}
}
But you could add yet another abstraction here:
class StringClipTextData : ClipTextData
{
public string ClipObjectData
{
get { return base.GetClipObjectData<string>(); }
set { base.SetClipObjectData(value); }
}
}

Related

Returning Unknown Type Without Generics

In my abstract base class AbstractType, I have an abstract auto-implemented property Value of unknown type. All my derived classes implement this property with their own types, such string or double. Normally, I know you would just make it AbstractType<T> and have the property be T Value { ... }. However, I don't have the ability to use generics in this case. In AbstractType, I'm trying to implement a method that returns a new derived class from AbstractType, so if I use generics, the caller has to know the type. If I make Value type object, then the caller has to wrap the object to the correct type - very inconvenient type/instance checking.
Here's what my class structure looks like (the method is simplified for the sake of demonstration):
abstract class AbstractType
{
public abstract ??? Value { get; set; }
AbstractType FromValue(int i)
{
if (i == 0)
return new NumberType();
else
return new StringType();
}
}
class NumberType : AbstractType
{
public override double Value { get; set; }
}
class StringType : AbstractType
{
public override string Value { get; set; }
}
Is there any way to do this without using generics?

Casting to derived class downward

I have a set of classes that derive one from another and the lower level has complete structure of what i need. the data stored and save is the highest level. in the highest level the Type is stored in the object. how can i cast down the highest level to the lowest. the generic see highest and T is highest which isn't helpful.
example :
Head class with couple core methods/fields :
[Serializable()]
public class CSelectionProperties
{
private Dictionary<string, string> lstProperties = new Dictionary<string, string>();
public Dictionary<string, string> getProperties { get { return lstProperties; } }
private Type objectType = null;
public Type ObjectType { get { return objectType; } set { objectType = value; } }
internal string FindProperty(string sProperty)
{
return FindProperty(sProperty, null);
}
internal string FindProperty(string sProperty, string sNullValue)
{
string sValue = sNullValue;
lstProperties.TryGetValue(sProperty, out sValue);
}
}
here an example of one of the many derived class :
[Serializable()]
public class CFilterSelectionProperties : CSelectionProperties, IFilterSelectionProperties
{
public double getAirVolume()
{
return Convert.ToDouble(FindProperty("INCFMValue", "0"));
}
}
Now all object using these property have the variable as CSelectionProperties so we can reuse everywhere same format.
When a class such as CFilterSelectionProperties gets created the Type get stored into the CSelectionProperties.ObjectTypeas a Type now another project receive a collection of CSelectionProperties and to properly read them i need to cast them as the proper type.
Right now i am going the old way
If(item is CFilterSelectionProperties)
{
RunDataAnalysis(item as CFilterSelectionProperties);
}
Else If (item is ...)
{
RunDataAnalysis(item as ...);
}
i use reflection and i stumble upon a case where i need the actual original class to loop the methods and retrieve some data. is there any way ?
Also some report will need to be open but again i have 4 class that derive from 1 single class that derive from CSelectionProperties at which point i don't have access to anything at all. I'm just trying to get away from If/Else which works fine.
As side note i tried going with and Activator but i can only find how to recreate a class as child type.
CFilterSelectionProperties oItem = new CFilterSelectionProperties();
MyObject.SelectionProperties = Activator.CreateInstance(oItem.ObjectType) as CSelectionProperties;
Not exactly sure if this is what you need but you can have a base class that "knows" the derived type:
class MyBase<T> {}
class A : MyBase<A> {}
class B : MyBase<B> {}
this way you can do this:
void Foo(MyBase<T> baseObj)
{
T derived = (T)(object)baseObj;
// use derived in a strongly-typed manner
}
Without knowing what RunDataAnalysis does it sounds like you can use virtual (or abstract) methods/properties in the base class that are overloaded in the derived classes. Then when you call those methods/properties in RunDataAnalysis you will be using the most derived version without having to cast the variable.
For example:
public class CSelectionProperties
{
... existing stuff
public virtual DataSet GetData(.. some parameters ...)
{
.. do stuff common to ALL subtypes
}
}
and
public class CFilterSelectionProperties : CSelectionProperties, IFilterSelectionProperties
{
public override DAtaSet GetData(... some parameters ...)
{
... do stuff common to THIS type and subtypes
}
}

Dynamic implementation of an Interface

Suppose I have an Interface with some properties:
public interface IDummy
{
string First {get;set;}
string Second {get;set;}
string Third {get;set;}
string Fourth {get;set;}
}
Now, I have a class which implements that interface:
public class DummyClass: IDummy
{
// ...
}
Is it possible, not to implement the interface properties explicitly and instead use DynamicObject? For example:
public class DummyClass: DynamicObject, IDummy
{
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
// Get the value from a Config file or SQLite db or something
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
// Get the value to a Config file or SQLite db or something
}
}
I am just curious if this is possible or not?
Thanks.
No, this is not possible.
If you are implementing an interface, you need to implement all of its members. C# is still a statically typed language, after all.
When you say a type implements an interface, you are saying it conforms to its contract. Not implementing all of the members means that you are not complying with the contract.
The compiler would see your code and will not assume that you have implemented the contract correctly (in a dynamic fashion) - it will fail to compile.
No, basically. An interface is for static typing; to satisfy an interface your type must actually provide a regular (non-dynamic) implementation. You could not claim to implement it (IDummy), and detect the names, but that could relate to any interface that uses those same names, not just IDummy.
You could make a wrapper.
class DummyWrapper : IDummy
{
private readonly DynamicObject _wrapped;
public DummyWrapper(DynamicObject wrapped)
{
_wrapped = wrapped;
}
string First
{
get { return _wrapped.First; }
set { _wrapped.First = value; }
}
string Second
{
get { return _wrapped.Second; }
set { _wrapped.Second = value; }
}
string Third
{
get { return _wrapped.Third; }
set { _wrapped.Third = value; }
}
string Fourth
{
get { return _wrapped.Fourth; }
set { _wrapped.Fourth = value; }
}
}
You might also be interested in these questions:
Automatically creating a wrapper to implement an interface
Dynamically implementing an interface in .NET 4.0 (C#)

Determining the correct data type from a name

I have created an application that allows users to capture information for entities based on a pre-defined template, which I create through a web interface.
So for instance I create a template and call it "Customer Template" with several properties like First Name, Last Name, Email address and I associate a "data type" to each property, which does not strictly map to a strongly typed type.
When the user then creates a new "Customer" a html form is generated with the appropriate properties / fields, which the user can provide and save.
The data types are called "Plain Text" or "Number" or "Currency" but do not map to a data type. What would be the best approach to associate a "number" to a strongly typed int, for instance, so that when I do operations on it that it is the correct type?
The number of "types" that the users will use are finite, maybe less than 10. Would I run into problems with a switch statement? Or is there another way?
I use c#.
I would use custom attributes to identify the CLR type mapped to your Form Types as such:
public enum FieldDataTypes
{
[FormTypeMetadata(typeof(string))]
PlainText = 0,
[FormTypeMetadata(typeof(int))]
Number = 1,
[FormTypeMetadata(typeof(decimal))]
Currency = 2
}
public class FormTypeMetadataAttribute : Attribute
{
private readonly Type _baseType = typeof(object);
public FormTypeMetadataAttribute(Type baseType)
{
if (baseType == null) throw new ArgumentNullException("baseType");
_baseType = baseType;
}
public Type BaseType { get { return _baseType; } }
}
// your 'FieldData' implementation would look like this...
public class FieldData
{
public FieldDataTypes FieldType { get; set; }
public object Value { get; set; }
}
You can retrieve the FieldDataTypes' attribute using reflection.
If you're using custom types for all of your data types, why not define each as a class that derives from a common abstract parent class like FormDataType. The parent class could expose some useful methods such as primitive data type association, while derived classes can handle validation, formatting, etc.
Here's a simple example where the parent class is generic. A separate interface definition is included for cases where the generic type argument T varies or is unknown:
public interface IFormDataType
{
object Value { get; }
Type PrimitiveType { get; }
string Format();
}
public abstract class FormDataType<T> : IFormDataType
{
object IFormDataType.Value { get { return Value; } }
public Type PrimitiveType { get { return typeof(T); } }
public T Value { get; private set; }
public FormDataType(T value)
{
Value = value;
}
public abstract string Format();
public override string ToString()
{
return Format();
}
}
public class Currency : FormDataType<decimal>
{
public Currency(decimal value)
: base(value)
{
//perform any validation if necessary
}
public override string Format()
{
return Value.ToString("C");
}
public static Currency Parse(string s)
{
return new Currency(decimal.Parse(s, NumberStyles.Currency));
}
}
To improve these classes, you might implement Equals, GetHashCode, IConvertible, serialization, validation, etc.

Changing property type in class that implements interface with object type property

I'm writing a TemplateEngine that will allow me to use my own markup in text based files. I'm wanting to add controls as plugins as the application matures. Currently i've got a structure like the following:
interface IControl
string Id
object Value
class Label : IControl
string Id
string Value
class Repeater : IControl
string Id
List<IControl> Value
Now you'll see the strange part right away in the Repeater class with the Value property. I was hoping that having the Value type as object in the interface would allow me the flexibility to expand the controls as i go along. The compiler doesn't like this and for good reason i guess.
Bottom line: I'm trying to get all control classes to implement the same interface but have different types for the Value property.
Does anyone have any suggestions how to accomplish this?
Note: Please don't go into suggesting things like use Spark View Engine for templating. There is a reason i'm creating extra work for myself.
Normally the Repeater would implement something different, like an IItemsControl for example.
EDIT 1
(removed for brevity)
EDIT 2
Ah okay, you can always use explicit interface implementation of course:
interface IControl
{
string Id { get; set; }
object Value { get; set; }
}
class Label : IControl
{
public string Id { get; set; }
public string Value { get; set; }
object IControl.Value
{
get { return this.Value; }
set { this.Value = (string)value; }
}
}
class Repeater : IControl
{
public string Id { get; set; }
public IList<IControl> Value { get; set; }
object IControl.Value
{
get { return this.Value; }
set { this.Value = (IList<IControl>)value; }
}
}
you could also use generics:
interface IControl<T>
{
string ID{get;set;}
T Value{get;set;}
}
class SomeControl : IControl<string>
{
public string ID{get;set}
public string Value{get;set;}
}
class SomeOtherControl : IControl<int>
{
public string ID{get;set}
public int Value{get;set;}
}
I like this better than the explicit interface idea if it's just one return value that needs to change. However, I think if you had several properties that each would return a different type, you wouldn't want to have IControl. At least, I wouldn't. In that case I would recommend the explicit interfaces.
Of course, this wouldn't work if you didn't have access to the source of IControl.
Edit: had a typo. Fixed
No, the compiler doesn't allow same name fields to be of different data types other than what is defined in the interface in derived classes.
The properties (since no fields are allowed in interface) should be implemented in the deriving classes and they need to have same data type. So, you cannot probably do it with properties without explicit declaration.
However, if you make Value to be returned by a function, then it works, but you need to check the return type because the return types should match for the function, otherwise you will get error that interface's function was not implemented.
interface IControl
{
object Value();
}
class A : IControl
{
string m_value = string.Empty;
public object Value() { return m_value; }
};
class B : IControl
{
List<IControl> m_value = new List<IControl>();
public object Value() { return m_value; }
};
....
object o = new B().Value();
if (o is List<IControl>)
MessageBox.Show("List");
[Update]
You have to be careful if explicitly defining the body of the properties. Having one name for two properties would be dangerous if implementation is not done carefully.
These two properties if contain different definition, it would be unexplainable for the final use of the interface and classes.
public IList<IControl> Value
object IControl.Value
See this example:
...
class Repeater : IControl
{
List<IControl> m_Value = new List<IControl>();
public IList<IControl> Value
{
get { return this.m_Value; }
set { this.m_Value = (IList<IControl>)value; }
}
object IControl.Value
{
get
{
return this.m_Value;
}
set
{
this.m_Value = new List<IControl>();
this.m_Value.Add(new Label());
this.m_Value.AddRange((List<IControl>)value);
}
}
}
...
Repeater b = new Repeater();
IControl i = b;
List<IControl> list = new List<IControl>();
list.Add(new Repeater());
i.Value = list;
You can observe that the list container in Repeater will have different values when data is added via IControl (because of the explicit definition of IContainer.Value).

Categories

Resources