Assign Properties from Method - c#

I have two class, base and inherited class like these
public class A
{
public string Prop1 { get; set; }
}
public class B : A
{
public string Prop2 { get; set; }
}
Now i have a method which return class A after populating properties values
public A GetPopulatedValues()
{
//code to populate values here
}
Now my question is, how to assign all the property values at once?
This works
public void Init()
{
var obj = new B();
obj.Prop1 = GetPopulatedValues().Prop1;
}
But i want something like this
public void Init()
{
var obj = new B();
obj = GetPopulatedValues();
}
Any ideas?

Create a constructor:
public Foo(string prop1, string prop2)
{
Prop1 = prop1;
Prop2 = prop2;
}
Or a copy constructor:
public Foo(Foo other)
{
Prop1 = other.Prop1;
Prop2 = other.Prop2;
}
Or use an object initializer:
var foo = new Foo { Prop1 = "Hello", Prop2 = "World" };
But as #RudiVisser says, you'll actually want to fix this in the GetPopulatedValues() method, by supplying a reference to the object you want to populate:
static class FooPopulator
{
public static void PopulateValues(Foo foo)
{
foo.Prop1 = "Hello";
foo.Prop2 = "World";
}
}
var foo = new Foo();
FooPopulator.PopulateValues(foo);
Now your foo object is usable and populatable, without having to alter the Foo class. Added bonus: when you add a property to populate (say Prop3), you will only have to alter the PopulateValues() method.
In your code you also have to do that, but then you'd need to also add the Prop3 assignment, which, if forgotten, will cause bugs.

I agree with #CodeCaster that this should probably be done with a constructor modification, but just to provide another alternative - why not make your GetPopulatedValues method accept an instance of A, and populate the values directly.
public void GetPopulatedValues(A instance)
{
instance.Prop1 = (whatever);
}
public void Init()
{
var obj = new B();
GetPopulatedValues(obj);
}

Related

Instanciate class A with values from instantiated class B when A and B inherit from same class (C#)

Say I have the following
public class A{
public string foo {get;set;}
public string bar {get;set;}
public int baz {get;set;}
}
public class B:A
{
public string wuz {get;set;}
}
public class C:A
{
public int yuh {get;set;}
}
If I then make an instance of B
var b = new B(){wuz="wow",foo="hello",bar="wordl",baz=18};
and later on I want to use those values of B in C, then I have to manually write
c = new C(){yuh=20, foo = b.foo, bar = b.bar, baz=b.baz};
isn't there a way to make c take the already instantiated values from B in a dynamic way, and parse them onto C? In this example it is easy to to, but say I have 500 properties then it's not feasible
(I'm fairly new to .NET thus there might be a typo/syntax error in the codeexample above, but I think the problem should be rather clear)
You can add a constructor to C that takes an instance of A (or if you really want to do that B). Would look something like this:
public class C:A
{
public C() {}
public C(A other)
{
this.foo = other.foo;
...
}
public int yuh {get;set;}
}
If you also want the same capability in B, you might want to add this kind of constructor to A, and call it from C:
public class A{
public A(){}
public A(A other)
{
this.foo = other.foo;
...
}
public string foo {get;set;}
public string bar {get;set;}
public int baz {get;set;}
}
public class C:A
{
public C(){}
public C(A other) : base(other) {}
public int yuh {get;set;}
}
In either case you can now create a new instance of Clike this:
c = new C(b){ yuh = 20};
Yes you can. You need to write method that will take B instance and sets all properties with reflection.
public C CreateCFromB(B bInstance)
{
var cInstance = new C();
foreach (var property in typeof(B).GetProperties())
{
var propertyValue = property.GetValue(bInstance, null);
property.SetValue(cInstance, propertyValue);
}
return cInstance;
}
You can take more generalized approach with generic types.
public TWhat CreateFrom<TFrom, TWhat>(TFrom tFromInstance)
where TWhat : TFrom, new()
{
var tWhatInstance = new TWhat();
foreach (var property in typeof(TFrom).GetProperties())
{
var propertyValue = property.GetValue(tFromInstance, null);
property.SetValue(tWhatInstance, propertyValue);
}
return tWhatInstance;
}

Saving item picked from list

Main class:
public class Main
{
private string param;
public Main(string param) { this.param = param; }
public List<Foo> Foos
{
get {return GetFoos();}
// add functionality of saving Foo (single item, not the whole list) here?
}
private List<Foo> GetFoos()
{
List<Foo> x = new List<Foo>();
return x;
}
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
// or maybe here?
}
}
Test class:
public class Test
{
public Test()
{
var main = new Main("hi!");
// usage 1
main.Foos.Find(p => p.Id == 1).Save(); // method visible here
var foo = new Main.Foo();
// usage 2
foo.Save(); // method not visible here
}
}
Comments in the code basically say everything:
1. I want to implement the Save() method of the object Foo.
2. Method can be called only if the Foo object is picked up from the list (usage 1).
3. Method can not be called from the Foo object created alone (usage 2).
4. Method must use private value of the property param passed during initialization of the main class.
You can use an interface to hide the method Save.
To do this, the Save method must be implemented explicitly.
Additionally you need a link to the main object. In your subclass Foo you can access the private attribute from Main directly.
Interface:
public interface IFoo
{
int Id { get; set; }
string Name { get; set; }
void Save();
}
Class:
public class Main
{
private string param;
private List<IFoo> foos = new List<IFoo>();
public Main(string param) { this.param = param; }
public List<IFoo> Foos
{
get { return this.foos; }
}
public void AddFoo(int pnId, string pnName)
{
this.foos.Add(new Foo(this) { Id = pnId, Name = pnName });
}
public class Foo : IFoo
{
private Main moParent;
public Foo() { }
public Foo(Main poParent)
{
this.moParent = poParent;
}
public int Id { get; set; }
public string Name { get; set; }
//Implement interface explicitly
void IFoo.Save()
{
if (this.moParent == null)
throw new InvalidOperationException("Parent not set");
Console.WriteLine($"Save with Param: {this.moParent.param}, Id: {this.Id} Name: {this.Name}");
//Save Item
}
}
}
Usage:
var main = new Main("hi!");
main.AddFoo(1, "Foo1");
// usage 1
main.Foos.Find(p => p.Id == 1).Save(); // method visible here
var foo = new Main.Foo();
// usage 2
//foo.Save(); // Save is not visible here

C# Set from another class and Get from another class

This's Class A
Class A
{
public string uname { get; set; }
public string fname { get; set; }
}
I set values by Class B
Class B
{
private void Main(){
A aGetSet = new A();
aGetSet.uname = "James";
aGetSet.fname = "Blunt";
}
}
But when I get values in Class C, it's always return null
Class C
{
private void Main() {
A aGetSet = new A();
string username = aGetSet.uname;
string fistname = aGetSet.fname;
}
}
Does anyone has solution for this problem?
The aGetSet declared in B is an object of A. The aGetSet declared in C is another object of A. They are completely independent of each other. Changing the values of one of the objects does not affect the values of the other.
To fix this problem, you need to make it so that you are accessing the same instance in B and C.
There are lots of ways to do this. I will show you how to use the singleton pattern.
class A
{
public string uname { get; set; }
public string fname { get; set; }
private A() {} // mark this private so that no other instances of A can be created
public static readonly A Instance = new A();
}
class B
{
public void Main(){
// here we are setting A.Instance, which is the only instance there is
A.Instance.uname = "James";
A.Instance.fname = "Blunt";
}
}
class C
{
public void Main() {
B b = new B();
b.Main();
string username = A.Instance.uname;
string fistname = A.Instance.fname;
}
}
Now you just need to call C.Main to make this work!
Your have 2 different objects in 2 classes. When you are using '= new A() ' it creates new instance.
The reason why you are getting null here:
string username = aGetSet.uname;
is default value for string type (as any reference type) is null.
To pass 'the same' object from class B into class C Main method change method in class C to public Main(ref A obj). That will not create a copy and use the same instance.
Call from class B:
A aObj = new A();
aGetSet.uname = "James";
aGetSet.fname = "Blunt";
C c = new C();
c.Main(ref aObj);

How to convert parent collection object to child collection object without looping in C#?

I have following object structure where B is derived from A and I am getting input as List<A> with lots of records. I want to convert thatList<A> to List<B> with easy steps (without looping). What is the best way to achieve the same.
Note: I don't want to use AutoMapper.
public class A
{
public A() { }
public virtual string Name
{
get;
set;
}
}
public class B : A
{
public B()
: base()
{
}
private string _name;
public override string Name
{
get
{
return _name;
}
set
{
_name = string.Concat("Hello ", base.Name);
}
}
public string Id
{
get { return "101"; }
}
}
You can do this by declaring constructor for class B from class A
in this way:
public B(A a):base()
{
this._name = a.Name;
}
And than do this:
var listA = new List<A> { new A { Name = "John" }, new A { Name = "Peter" }, new A { Name = "Julia" } };
List<B> listB = listA.Select(x=> new B(x)).ToList();
Based on the comments this is the output, though I still don't really understand the point.
List<A> thisIsA = new List<A>();
thisIsA.Add(new B());
List<B> thisIsB = new List<B>();
thisIsB.AddRange(thisIsA.Cast<B>());

C# How to access a class member by Binding

I want to access a class member by binding, but without any UI nor XAML code.
class Foo {
public int Value { get; set; }
}
class Bar {
public Foo foo { get; set; }
}
Bar bar = new Bar() {
foo = new Foo() {
Value = 2
}
}
Binding b = new System.Windows.Data.Binding("foo.Value");
b.Source = bar;
// Now I want a method which returns bar.foo.Value, would be like that:
int value = b.GET_VALUE(); // this method would return 2
Is there such a method ?
I found the answer, thanks to:
How to get class members values having string of their names?
No need of Binding class:
public static class Extensions
{
public static object GetPropertyValue(this object Obj, string PropertyName)
{
object Value = Obj;
foreach (string Property in PropertyName.Split('.'))
{
if (Value == null)
break;
Value = Value.GetType().GetProperty(Property).GetValue(Value, null);
}
return Value;
}
}
Usage:
class Foo {
public int Value { get; set; }
}
class Bar {
public Foo foo { get; set; }
}
Bar bar = new Bar() {
foo = new Foo() {
Value = 2
}
}
bar.GetPropertyValue("foo.Value"); // 2
bar.foo = null;
bar.GetPropertyValue("foo.Value"); // null

Categories