Static method return base class instance - c#

I have the following classes:
//some base class
public abstract class MyObject<T>{
public static T FromObject(object anotherObject){
var t = Activator.CreateInstance<T>();
// some reflection logic here
return t;
}
}
public class Product: MyObject<Product>{
}
public class ProductCart: MyObject<ProductCart>{
public ICollection<Product> Products{get;set;}
}
public class Basket: ProductCart{
public int BasketId{get;set;}
}
public class Order: ProductCart{
public int OrderId{get;set;}
}
So now I could build my model like this:
var products = serviceContext.Products.Select(Product.FromObject).ToList(); // no problem here
var basket = Basket.FromObject(serviceContext.Basket); // problem is here - instance of ProductCart is returned
var order = Order.FromObject(serviceContext.Order); // same problem, instance of ProductCart
Is there a way somehow to solve it and get converted Basket and Order instead of base ProductCart?
The goal is:
var basket = Basket.FromObject(serviceContext.Basket); // return instance of Basket inherited from ProductCart
Thanks for helping.

If you can change the class definitions, you can pass along the type to ProductCart, like so:
public class ProductCart<T> : MyObject<T> { }
public class Basket : ProductCart<Basket> { }
public class Order : ProductCart<Order> {}
In your definition you tell Basket.FromObject to explicitly return ProductCarts (by inheriting from MyObject<ProductCart>).
And if you're unable to change the inherit tree, you can choose to hide the original method (or place it in a factory):
public class Basket : ProductCart
{
public int BasketId { get; set; }
public Basket FromObject(object anotherObject)
{
return MyObject<Basket>.FromObject(anotherObject);
}
}

That's because Basket is a MyObject<ProductCart>, and not a MyObject<Basket>.
If you don't want to redefine your hierarchy, you should define the return type of the static method according to the object you pass, like in this example:
using System;
public abstract class MyObject<T> {
public static TOtherObject FromObject<TOtherObject>(TOtherObject anotherObject) where TOtherObject : MyObject<T> {
var newOtherTypeInstance = Activator.CreateInstance<TOtherObject>();
// some reflection logic here
return newOtherTypeInstance;
}
}
public class ProductCart : MyObject<ProductCart> {
}
public class Basket : ProductCart {
public int BasketId { get; set; }
}
public class Order : ProductCart {
public int OrderId { get; set; }
}
class Program {
static void Main(string[] args) {
Order o = new Order();
var basket = Basket.FromObject(o);
}
}
Of course, at this point the actual implementation of the comment "some reflection logic here" could get much more complicated :)

Related

C# - CS0572 Error When Trying to Populate a Class

C# Newbie Here.
I have a class below:
namespace CompanyDevice.DeviceResponseClasses
{
public class DeviceStatusClass
{
public class Root
{
public static string RequestCommand { get; set; }
}
}
}
In another namespace I have:
namespace CompanyDevice
{
public class StatusController : ApiController
{
public DeviceStatusClass Get()
{
var returnStatus = new DeviceStatusClass();
returnStatus.Root.RequestCommand = "Hello"; //'Root' is causing a CS0572 error
return returnStatus;
}
}
}
I'm sure I'm making some rudimentary error here. Could you please help me find it? Thanks.
You access static properties from the type, not from the instance.
DeviceStatusClass.Root.RequestCommand = "Command";
Because the property RequestCommand is static, there will only ever be one. Perhaps this is what you want, but likely is not based on your usage.
You can remove the static keyword from RequestCommand, then you can access it through the instance, however you will need to add a field or property for the instance of Root inside of DeviceStatusClass.
public class DeviceStatusClass
{
public Root root = new Root();
public class Root
{
public string RequestCommand { get; set; }
}
}
And use like you did originally.
public class StatusController : ApiController
{
public DeviceStatusClass Get()
{
var returnStatus = new DeviceStatusClass();
returnStatus.root.RequestCommand = "Hello";
return returnStatus;
}
}
You maybe have a java background. In c# nested classes only change the names, they do not make the parent class contain an instance of a child class
namespace CompanyDevice.DeviceResponseClasses
{
public class DeviceStatusClass
{
public class Root
{
public static string RequestCommand { get; set; }
}
public Root DeviceRoot {get;set;} <<<=== add this
}
}
and then
returnStatus.DeviceRoot.RequestCommand = "Hello";

c# change GET implementation get<typed>() to get()

I have some problem I can not resolve.
I have a class GlobalTest derived from GlobalObjectImpl:
public class GlobalTest : GlobalObjectImpl
{
public string LastProcessDay { get; set; }
}
It was called from this:
var global = GlobalTest.Get<GlobalTest>();
The GlobalObjectImpl is declared like this:
public abstract class GlobalObjectImpl
{
public bool Save()
{
return DataStore.SaveGlobal(this);
}
public static T Get<T>() where T : GlobalObjectImpl
{
return DataStore.GetGlobal<T>();
}
}
I want to get my LastProceedDate like this:
var global = GlobalTest.Get();
But it fails.
You can make your abstract class generic like the following:
public abstract class Base<T>
{
public static T Get() => throw new NotImplementedException();
}
public class Derived : Base<Derived> { }
And then just call Get
var foo = Derived.Get();
I all, big thank to you, i have succesfully implemented my class
My Abstract Class
public abstract class GlobalTreeObjectImpl<T>
{
public bool Save()
{
return NeoStore.SaveGlobal(this);
}
public static T Get() => NeoStore.GetGlobal<T>();
}
}
Class use abstract class
public class GlobalTest : GlobalTreeObjectImpl<GlobalAntai>
{
public string LastProcessDay { get; set; }
}
Usage of this on my code
var global = GlobalTest.Get();
LoggerManager.LogInfo($"Global LastProcessDay : {global.LastProcessDay} - {DateTime.UtcNow}");
global.LastProcessDay = DateTime.Now.AddDays(10).ToString("yyyy-MM-ddThhh:mmm:ssZ");
global.Save();
global = GlobalTest.Get();
LoggerManager.LogInfo($"Global LastProcessDay : {global.LastProcessDay} - {DateTime.UtcNow}");

Specify Generic type and interface

I need to have a list where all items extend class A and implement interface I. Additionally class A might be multiple parents up in the hierarchy.
If all the classes were direct descendants of class A I could just use an Abstract class that implements I as the generic and use that, but my use case doesn't allow for this.
is there a way to tell a List that its elements must both extend class A and implement interface I ? List<A,I> ? If not is there another way around this?
Example Code:
public class A
{
// Class belongs to a third party library
}
public class B : A
{
// Class belongs to a third party library
public string Text{ get; set; }
}
public class C : A
{
// Class belongs to a third party library
public string Other{ get; set; }
}
interface I
{
// Belongs to me
bool shouldSend();
string getName();
string getValue();
}
public class MyClass : B, I
{
public string Name{ get; set; }
public function myClass(ObjectWithName obj)
{
Name = obj.Name;
}
public string getValue()
{
return Text;
}
public bool shouldSend()
{
return true;
}
}
public class MyClass2 : C, I
{
public string Name{ get; set; }
public function myClass(ObjectWithName obj)
{
Name = obj.Name;
}
public string getValue()
{
return Other;
}
public bool shouldSend()
{
return true;
}
}
public class mainActions
{
// Here is where I need the list to use both restrictions
public List<A,I> myList;
// The class I need to use these things in
public function mainActions(List<ObjectWithName> elements)
{
ThirdPartyCollection TPC = new ThirdPartyCollection();
foreach(var el in elements)
{
MyList.Add(new MyClass(el));
MyList.Add(new MyClass2(el));
// TPC.Add accepts implementations of A here
TPC.Add(MyList.ElementAt(MyList.Count - 1));
TPC.Add(MyList.ElementAt(MyList.Count - 2));
}
}
public function doThisLater()
{
foreach(var el in myList)
{
if(el.shouldSend())
{
// I need an implementation of I here
doSomethingElse(el.getName(), el.getValue());
}
}
}
}
EDIT: For anyone coming in search of an answer here in the future, it doesn't seem to be possible. Instead I used #servys answer and made a new list to hold my sub class objects:
public class MyList<T> : List<T> where T : A, I
{
}
Then I kept different lists for each subclass:
protected MyList<MyClass> MCList = new MyList<MyClass>();
protected MyList<MyClass2> MCList2 = new MyList<MyClass2>();
When you specify generic constraints you can specify as many as you want, and all of them must be met, so you can simply add a generic constraint of A and I to your type, and a type has to meet both of those constraints to be a valid generic argument.
public class ClassThatNeedsABetterName<T> : List<T>
where T : A, I
{ }

Inherit from generic type as interface

I am attempting to do something similar to:
public interface IView<T> : T where T : class
{
T SomeParam {get;}
}
So that i can later do
public class SomeView : IView<ISomeView>
{
}
Is it possible to specify inheritance using generics in this way or do i have to go the long way round and explicitly specify both interfaces when defining the class and do:
public interface IView<T>
{
T SomeParam {get;}
}
public class SomeView : IView<ISomeView>, ISomeView
{
}
This isn't possible, but your goal may be achievable with conversion operators. It seems that what you're trying to do is make it possible to pass an IView<T> as the T object which it contains. You could write a base class like this:
public abstract class ViewBase<T> {
public abstract T SomeParam { get; }
public static implicit operator T(ViewBase<T> view) {
return view.SomeParam;
}
}
Then, if you define a class like:
public class SomeView : ViewBase<ISomeView> { }
It can be accepted anywhere an ISomeView is expected:
ISomeView view = new SomeView();
Short answer: It is not possible. See this post
An Interface can't derive from a class. However nothing prevent you from doing this:
public interface ISomeView
{
}
public interface IView<out T> where T:class
{
T SomeParam { get; }
}
public class SomeView:IView<ISomeView>
{
public ISomeView SomeParam { get; set; }
}
Edit:
If you don't want to implement the T SomeParam { get; } each time you need to have an implementation, Does this would work?
public interface ISomeView
{
}
public abstract class BaseView<T> where T : class
{
public T SomeParam { get; set; }
}
public class SomeView : BaseView<ISomeView>{
}
In both case this would work:
public class main
{
public class OneOfThoseView : ISomeView
{
}
public main()
{
OneOfThoseView oneOfThose = new OneOfThoseView();
SomeView x = new SomeView();
x.SomeParam = oneOfThose;
}
}
Edit 2:
Not exactly what you want to do but this would force your SomeView class to return a BaseView<SomeView> class
public interface ISomeView
{
}
public abstract class BaseView<T> where T : BaseView<T>
{
public T SomeParam { get; set; }
}
public class SomeView : BaseView<SomeView>
{
}
Now only this would work.
public main()
{
SomeView y= new SomeView ();
SomeView x = new SomeView();
x.SomeParam = y;
}

Common base class initialization

Take the scenario
BaseA -> SubB -> SubSubC
Explanation: SubSubC class inherits SubB class. The SubB class inherits BaseA class
BaseA -> SubD -> SubSubE
Explanation: SubSubE class inherits SubD class. The SubB class inherits BaseA class
So..on..
So there are many class that has its grand parent class as BaseA . The BaseA class has some properties that are common to all the methods. ex: CustomerID, LastLogin, UniqueName etc.
This is how the class is designed in the service which I'm consuming.
My doubt is While calling the service methods, all the methods would expect a parameter of any SubSub class. Can anyone please tell me, is there any way if I could assign values to the properties of the BaseA in one place so that while creating the SubSub objects I did not need to fill the base properties each time?
I'm using C# as my language.
Code:
public class BaseA
{
public int CustomerId { get; set; }
public string UniqueName { get; set; }
}
public class SubB : BaseA
{
}
public class SubSubC : SubB
{
}
public class SubD : BaseA
{
}
public class SubSubE : SubD
{
}
public class MyMain
{
public void SendRequestToService1()
{
(new MyServiceObject()).ServiceMethod1(new SubSubC());
}
public void SendRequestToService2()
{
(new MyServiceObject()).ServiceMethod2(new SubSubE());
}
}
In the above code, in SendRequestToService1 and SendRequestToService2 , i need to initialise the base class properties CustomerId and UniqueName.
Ex:
(new SubSubC(){ CustomerId=2, UniqueName="XXBB" });
If there are many methods, I need to initialize these properties each time for their respective classes. Is there a way I can initialize the base properties CustomerId and UniqueName in one place so that the inheriting classes(SubSubC,SubSubE here) no need to initialize when their objects are created?
Are you looking for the following functionality?
//dummy class replacing the service object and it's methods
public class MyServiceObject
{
public void ServiceMethod1(SubSubC param)
{ }
public void ServiceMethod2(SubSubE param)
{ }
}
public class BaseA
{
public int CustomerId { get; set; }
public string UniqueName { get; set; }
}
public class SubB : BaseA
{
}
public class SubSubC : SubB
{
}
public class SubD : BaseA
{
}
public class SubSubE : SubD
{
}
public class MyMain
{
//declare the SubSub objects
//SubSubC subSubC;
//SubSubE subSubE;
BaseA baseA;
public MyMain()
{
//assign the values to each class in the MyMain contrsuctor
baseA = new BaseA { CustomerId = 2, UniqueName = "XXBB" };
}
public void SendRequestToService1()
{
var subSub=new SubSubC();
(new MyServiceObject()).ServiceMethod1(Initialize(subSub));
}
public void SendRequestToService2()
{
var subSub = new SubSubE();
(new MyServiceObject()).ServiceMethod2(Initialize(subSub));
}
private T Initialize<T>(T subSub) where T:BaseA
{
subSub.CustomerId = baseA.CustomerId;
subSub.UniqueName = baseA.UniqueName;
return subSub;
}
}
class Program
{
static void Main(string[] args)
{
MyMain myMain = new MyMain();
myMain.SendRequestToService1();
myMain.SendRequestToService2();
}
}
Are you asking about calling base constructors? If so:
class SubSubC : SubB
{
public object CProperty { get; private set; }
public SubSubC(object cProperty, string bProperty, int id) : base(bProperty, id)
{
CProperty = cProperty;
}
}
class SubB : BaseA
{
public string BProperty { get; private set; }
public SubB(string bProperty, int id) : base(id)
{
BProperty = bProperty;
}
}
class BaseA
{
public int ID { get; private set; }
public BaseA(int id)
{
ID = id;
}
}
Or are you asking about initializing objects in a method? If so (assume the setters are public in the following code, unlike in the preceding):
void SetSubSubCProperties(SubSubC c, object cProperty, string bProperty, int id)
{
c.CProperty = cProperty;
SetSubBProperties(c, bProperty, id);
}
void SetSubBProperties(SubB b, string bProperty, int id)
{
b.BProperty = bProperty;
SetBaseAProperties(b, id);
}
void SetBaseAProperties(BaseA a, int id)
{
a.ID = id;
}
Ok, Alex Filipovici's answer, it looks like you want to initialize an instance of a derived class by copying the base class properties from an instance of a different derived class. In that case, to reduce the duplication in Alex's answer, you can do this:
void Initialize(BaseA source, BaseA target)
{
target.CustomerID = source.CustomerID;
target.UniqueName = source.UniqueName;
}
Then, to modify his example:
public void SendRequestToService1()
{
var subSub = new SubSubC();
Initialize(this.baseA, subSub);
(new MyServiceObject()).ServiceMethod1(subSub);
}
public void SendRequestToService2()
{
var subSub = new SubSubE();
Initialize(this.baseA, subSub);
(new MyServiceObject()).ServiceMethod2(subSub);
}
Not sure I understand your question.
public class A {
public int ID { get; set; }
}
public class B : A {
}
you can do B b = new B() and then b.ID = 12.
Or, if you have a method that gets a parameter of type A in your service you can change the value in the same way.
public void doSomething(A a) {
a.ID = 12;
}
and call the method with instances of B - doSomething(new B())

Categories

Resources