I have a class like this:
public class Student
{
private string NumberP;
public string Number
{
get{return NumberP;}
set{NumberP=value;}
}
}
public class School
{
private string NameP;
public string Name
{
get{return NameP;}
set{NameP=value;}
}
}
I want to declare a Type from another class like (school or Student), but I don't know its type.
How Can I declare a property unknown type. I will set unknown type another time
public class MyClass
{
public UnKnownType
{
}
}
Since the Student and School types do not have any relationship between them you could use the object type:
public class MyClass
{
public object SomeProperty { get; set; }
}
and use like this:
MyClass myClass = new MyClass();
myClass.SomeProperty = new Student();
or make the containing class generic:
public class MyClass<T>
{
public T SomeProperty { get; set; }
}
and then you could use like this:
MyClass<Student> myClass = new MyClass<Student>();
myClass.SomeProperty = new Student();
public class MyClass
{
private object myField = null;
public object MyProperty
{
get { /* ... */ }
set { /* ... */ }
}
}
Related
For example, let's say I have the following class:
public class MyClass
{
public int Prop1 { get; private set; }
public int Prop2 { get; private set; }
public int Prop3 { get; private set; }
public MyClass CreateFromRaw (MyClass thePostedObject)
{
MyClass newObj = new MyClass()
{
Prop1 = thePostedObject.Prop1,
Prop2 = thePostedObject.Prop2,
Prop3 = thePostedObject.Prop3
};
}
}
And I receive it in a POST request like this:
[Route("receive")]
[HttpPost]
public MyClass GetDocumentTemplateByDocTemplateId([FromBody]MyClass thePostedObject)
{
return MyClass.CreateFromRaw(thePostedObject);
}
Since each prop in MyClass is a private set, they're not parsed out into a MyClass object from thePostedObject. How would I keep the props as private set's, while still being able to parse from a POST request? Would I need to create a new class with those props as NOT private set?
I have an class object from an external library that I want to add some additional properties to.
Let's say the external class is:
public class ExternalClass
{
public string EXproperty1 {get;set;}
public string EXproperty2 {get;set;}
public string EXproperty3 {get;set;}
public ExternalClass(){}
}
and I have a list of these object which gets populated as
List<ExternalClass> listOfExternalClass=new List<ExternalClass>();
listOfExternalClass=GetListOfExternalClass();
I can extend this class by creating a new class, adding the additional properties and making the external class a property.
public class NewClass
{
public ExternalClass ExternalClass {get;set;}
public string NewProperty1 {get;set;}
public string NewProperty2 {get;set;}
public NewClass(){}
public NewClass(ExternalClass externalClass){
this.ExternalClass=externalClass;
}
}
But to convert by original list of the external classes to a list of the new classes I would have to create a new list of new classes and iterate through the original list creating a new object and adding it to the list, like
List<NewClass> listOfNewClass=new List<NewClass>();
foreach(var externalClass in listOfExternalClass)
{
listOfNewClass.Add(new NewClass(externalClass));
}
I would then be able to access the external properties like
listOfNewClass.FirstOrDefault().ExternalClass.EXproperty1;
Can I do this with inheritance or is there a more efficient method?
Ideally I would like to end up with by calling the properties like:
listOfNewClass.FirstOrDefault().EXproperty1;
This can certainly be done with inheritance. Consider the following.
//Inherit from our external class
public class NewClass: ExternalClass
{
//Note we do not have a copy of an ExternalClass object here.
//This class itself will now have all of its instance members.
public string NewProperty1 {get;set;}
public string NewProperty2 {get;set;}
//If it has parameters include those parameters in NewClass() and add them to base().
//This is important so we don't have to write all the properties ourself.
//In some cases it's even impossible to write to those properties making this approach mandatory.
public NewClass()
{
}
}
Few things to know:
Your code is called a wrapper. This is because it "wraps" another class or group of classes.
You cannot inherit from class marked as sealed.
In C# classes are not sealed by default. If they're sealed the developer has intentionally prevented you from inheriting from the class. This is usually for a good reason.
If you can actually extend the External class that would be easy to accomplish:
public class NewClass: ExternalClass
{
public string NewProperty1 {get;set;}
public string NewProperty2 {get;set;}
public NewClass(){}
public NewClass(ExternalClass externalClass){
// you would have to copy all the properties
this.EXproperty1 = externalClass.EXproperty1;
}
}
Yes inheritance is what you are looking for:
public class ExternalClass
{
public string EXproperty1 { get; set; }
public string EXproperty2 { get; set; }
public string EXproperty3 { get; set; }
public ExternalClass() { }
}
public class NewClass:ExternalClass
{
public string NewProperty1 { get; set; }
public string NewProperty2 { get; set; }
public NewClass() { }
}
If you wish for (or need) delegation instead of a copy you can do:
public class NewClass
{
public ExternalClass ExternalClass {get;set;}
public string NewProperty1 {get;set;}
public string NewProperty2 {get;set;}
public string EXproperty1 {get { return this.ExternalClass.EXproperty1; };set{ this.ExternalClass.EXproperty1 = value; }; }
public string EXproperty2 {get { return this.ExternalClass.EXproperty2; };set{ this.ExternalClass.EXproperty2 = value; }; }
public string EXproperty3 {get { return this.ExternalClass.EXproperty3; };set{ this.ExternalClass.EXproperty3 = value; }; }
public NewClass(){}
public NewClass(ExternalClass externalClass){
this.ExternalClass=externalClass;
}
}
Instead of working against specific types, work against interfaces.
Below I am showing a mix of facade pattern and adapter pattern to 'transform' external data to a well-defined interface (IDocument), effectively abstracting things your are working on.
Example 1 : query about an interface
Here are the types you'll work against:
public interface IDocument {
string Name { get; set; }
}
public interface IMetadata {
string[] Tags { get; set; }
}
This is your own representation, should you need any:
public class RichDocument : IDocument, IMetadata {
public string Name { get; set; }
public string[] Tags { get; set; }
}
This is the wrapper against external data:
(a bastard mix of facade and/or adapter concepts)
public class ExternalClass {
public string Whatever { get; set; }
}
public class ExternalDocument : IDocument /* only a basic object */ {
private readonly ExternalClass _class;
public ExternalDocument(ExternalClass #class) {
_class = #class;
}
public string Name {
get { return _class.Whatever; }
set { _class.Whatever = value; }
}
}
And a demo on how to use all that:
internal class Demo1 {
public Demo1() {
var documents = new List<IDocument> {
new ExternalDocument(new ExternalClass()),
new RichDocument()
};
foreach (var document in documents){
var name = document.Name;
Console.WriteLine(name);
// see if it implements some interface and do something with it
var metadata = document as IMetadata;
if (metadata != null) {
Console.WriteLine(metadata.Tags);
}
}
}
}
Example 2 : query about a component
This is a bit more involved by pushing the concept to treat everything in an uniform manner, you can find it in .NET framework, game development or whatever ...
Definitions you'll work against:
public interface IContainer {
IList<IComponent> Components { get; }
}
public interface IComponent {
// it can be/do anything
}
Some components you'll query about:
public interface IDocument : IComponent {
string Name { get; set; }
}
public interface IMetadata : IComponent {
string[] Tags { get; set; }
}
Your 'internal' type:
public class Container : IContainer {
public Container() {
Components = new List<IComponent>();
}
public IList<IComponent> Components { get; }
}
Your 'wrapper' against external data:
public class ExternalClass {
public string Whatever { get; set; }
}
public class ExternalContainer : IContainer {
private readonly List<IComponent> _components;
public ExternalContainer(ExternalClass #class) {
_components = new List<IComponent> {new ExternalDocument(#class)};
}
public IList<IComponent> Components {
get { return _components; }
}
}
public class ExternalDocument : IDocument {
private readonly ExternalClass _class;
public ExternalDocument(ExternalClass #class) {
_class = #class;
}
public string Name {
get { return _class.Whatever; }
set { _class.Whatever = value; }
}
}
And a usage example:
public class Demo2 {
public Demo2() {
var containers = new List<IContainer> {
new ExternalContainer(new ExternalClass()),
new Container()
};
foreach (var container in containers) {
// query container for some components
var components = container.Components;
var document = components.OfType<IDocument>().FirstOrDefault();
if (document != null) {
Console.WriteLine(document.Name);
}
var metadata = components.OfType<IMetadata>().FirstOrDefault();
if (metadata != null) {
Console.WriteLine(metadata.Tags);
}
}
}
}
Notes
The problem with inheritance is that it is a very rigid approach and generally once you start doing it and at some point you hit a wall and want to revert, it's hard to get out of it.
By working against abstractions things are more flexible and things are decoupled.
Here are two examples that might incite you to change your approach:
Composition over inheritance
Using Components
Using .net XmlSerializer and the following structure:
public class SomeClass {
[XmlElement("some-string")]
public string SomeString { get; set; }
}
I need the above to produce :
<someclass>
<some-string alt-name="someotherstring">
StringValue
</some-string>
</someclass>
But i dont want to have to define types for somestring, some int, somebool, yetanotherstring etc every time i want to add a standard type as a porperty to my classes.
Any way I can override xlement to handle this maybe?
Produce wrappers for base types and conversion operators to alleviate object construction:
[Serializable()]
public partial class StringWrapper
{
[XmlAttribute("alt-name")]
public string altname { get; set; }
[XmlText()]
public string Value { get; set; }
public static implicit operator string (StringWrapper sw) { return sw.Value; }
public static implicit operator StringWrapper (string s) {
return new StringWrapper() { altname = "someotherstring", Value = s };
}
}
Use wrappers instead of base types where needed:
[Serializable()]
[XmlRoot(Namespace = "someclass", IsNullable = false)]
public class someclass
{
[XmlElement("some-string")]
public StringWrapper somestring { get; set; }
}
Use it like:
var srlz = new XmlSerializer(typeof(someclass));
srlz.Serialize(Console.Out, new someclass() { somestring = "StringValue" });
The only way to do that via XmlSerializer is:
[XmlRoot("someclass")]
public class SomeClass {
[XmlElement("some-string")]
public SomeOtherClass Foo {get;set;}
}
public class SomeOtherClass {
[XmlText]
public string Text {get;set;}
[XmlAttribute("alt-name")]
public string Bar {get;set;}
}
Alternatively: use XmlDocument / XDocument instead of XmlSerializer.
I have a json comprising list of MyFacebookClass and when i am deserializing the list of MyFacebookClass then i am getting the error that no blank constructor defined for CustomObject though i have already defined constructor as shown below,so please help me out.
public class MyFacebookClass
{
public MyFacebookClass
{
data =new List<CustomObject>();
}
public string Name{get;set;}
public int Id{get;set;}
public List<CustomObject> data {get;set;}
}
public class CustomObject
{
public CustomObject()
{
}
public string id {get;set;}
public string name {get;set;}
}
I am using:
List<MyFacebookClass> routes_list = new List<MyFacebookClass>();
JavaScriptSerializer jSerializer = new JavaScriptSerializer();
routes_list = jSerializer.Deserialize<List<MyFacebookClass>>(json);
you have no constructor for CustomObject in the code that you have posted. basically, a constructor is a method that has no return type and is the same name as the declaring class. You DO have a constructor for your MyFacebookClass here is the MSDN documentation on constructors.
public class CustomObject
{
public CustomObject()
{
/* now you have a constructor */
}
public string id {get;set;}
public string name {get;set;}
}
Working perfectly fine. Only issue I found in your code was, MyFacebookClass class constructor should have brackets
public class MyFacebookClass
{
public MyFacebookClass()
{
data = new List<CustomObject>();
}
public string Name { get; set; }
public int Id { get; set; }
public List<CustomObject> data { get; set; }
}
public class CustomObject
{
public CustomObject()
{
/* now you have a constructor */
}
public string id { get; set; }
public string name { get; set; }
}
public class Main
{
public List<MyFacebookClass> Deserialize(string json)
{
List<MyFacebookClass> routes_list = new List<MyFacebookClass>();
JavaScriptSerializer jSerializer = new JavaScriptSerializer();
return jSerializer.Deserialize<List<MyFacebookClass>>(json);
}
}
[TestMethod()]
public void doSomethingTest()
{
Main target = new Main(); // TODO: Initialize to an appropriate value
Assert.AreEqual(target.Deserialize(""), null);
}
If i have a ClassA
public class ClassA
{
public string name;
}
Where Attribute Name is Public ,and it can be modified from Anywhere .
Than i have a ClassB
public class ClassB : ClassA
{
private string name;//But it's not Woking ,name is still public
}
...which Inherit's ClassA ,but i need at ClassB to make name as Private Field.
So if i create an Object of Type ClassB than ClassB.name cannot be modified .
just don't publish the field but accessors:
public class ClassA
{
private string _name;
public string Name { get { return _name; } protected set { _name = value; } }
}
public class ClassB : ClassA
{
/* nothing left to do - you can set Name in here but not from outside */
}
This is not possible. You can not change visibility of base class's field.
Assuming you cannot change A, do not use inheritance, but aggregation and delegation:
public class A {
public string name;
public int f() { return 42; }
}
public class B {
private A a;
public int f() { return a.f(); }
public string getName() { return a.name; }
}
Carsten Konig's method is a good way, and here is an alternative.
public class ClassA {
public virtual string Name {
get;
private set;
}
}
public class ClassB : ClassA {
public override string Name {
get {
return base.Name;
}
}
}
Hm. There is a pair of tricks for this. But none of them is what you really want. One is:
public class ClassA
{
protected string name;
public string Name { get { return name; } public set { name = value; } }
}
public class ClassB : ClassA
{
public new string Name { get { return base.name; } }
}
If you don't have control over ClassA, you can do this:
void Main()
{
var b = new ClassB();
var a = (ClassA)b;
a.name = "hello";
b.PrintName();
}
class ClassA {
public string name;
}
class ClassB : ClassA {
private new string name;
public void PrintName() {
Console.WriteLine(base.name);
}
}