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
Related
I'm in search of a simple way to test that a collection contains logically equivalent object (ignoring instance) in c#.
public class BarObject
{
public string name { get; set; }
public string info { get; set; }
}
public class Foo
{
public Foo() { }
public IEnumerable<BarObject> Bars { get; set; } =
new List<BarObject>()
{
new BarObject() { name = "johndoe", info = "wierdo" }
};
}
[TestClass]
public class FooTests
{
[TestMethod]
public void TestDefaultInList()
{
Foo foo = new Foo();
//Using NUnit
CollectionAssert.Contains(foo.Bars.ToList(),
new BarObject() { name = "johndoe", info = "wierdo" }
);
}
}
The issue that I believe that I am having is that it is checking the instance of the object instead of the values within. How do I test that there is an object with specific values in an array simply without writing my own comparers?
there is a concept about inheritance which I do not quite understand.
I have a
protected DeveloperReport DeveloperReport; // Field
Wouldn't PersonalInfoBuilder be able to access that field ?
If yes,
public PersonalInfoBuilder MyPersonalInfo => new PersonalInfoBuilder(DeveloperReport);
Why do I still have to pass the DeveloperReport(field) into PersonalInfoBuilder constructor, when I can
just modify the protected DeveloperReport field by calling new PersonalInfoBuilder(), instead of
new PersonalInfoBuilder(DeveloperReport)?
And, how the concept of "return this" return the changes made to DeveloperReport(field) back to
DeveloperReportBuilder?
Thanks !
class DeveloperReport
{
// Properties
public int Id { get; set; }
public string Name { get; set; }
public DeveloperLevel Level { get; set; }
public int WorkingHours { get; set; }
public int HourlyRate { get; set; }
// Methods
public double CalculateSalary() => WorkingHours * HourlyRate;
}
class DeveloperReportBuilder
{
protected DeveloperReport DeveloperReport;
public PersonalInfoBuilder MyPersonalInfo => new PersonalInfoBuilder(DeveloperReport);
public DeveloperReportBuilder()
{
DeveloperReport = new DeveloperReport();
}
// return developer report.
public DeveloperReport Build() => DeveloperReport;
}
class PersonalInfoBuilder : DeveloperReportBuilder
{
public PersonalInfoBuilder(DeveloperReport report)
{
DeveloperReport = report;
}
public PersonalInfoBuilder()
{
}
public PersonalInfoBuilder NameIs(string name)
{
DeveloperReport.Name = name;
return this;
}
public PersonalInfoBuilder IDis(int id)
{
DeveloperReport.Id = id;
return this;
}
}
You only have to pass the report instance if you want to have both instances of DeveloperReportBuilder and PersonalInfoBuilder have acces to the same instance of DeveloperReport.
Inheritance will not copy the instance values.
I have a ParentClass. Two classes are inherit from it, FirstChildClass and SecondChildClass. A class MultipleValueTypes contains a Dictionary and a method that adds values to it. My intention is to be able to pass values of different classes, which inherit from the same abstract class to the value parameter of the Dictionary. Therefore, I initialize the dictionary with the value List<ParentClass> so that I would be able to add objects made with the child classes to the Dictionary. I can do this, but I cannot access them, therefore in the abstract class I create a way to tell them apart, a virtual method that both the children classes override to return their own class type.
I test the values they return against the enum itself and based on whether the condition is fulfilled, the object would be casted as what it is instead of a List<ParentClass>. Is this the wrong approach? Is this impossible?
I think it should work, because in my thinking the FirstObject and SecondObject are still objects of their respective classes, so casting should work and I should be able to access the overridden method.
What doesn't work: I cannot access the method that returns what type of class it is, because it only gets methods from the List<ParentClass>.
What I've tried so far: searching for a way to access the method, but I did not find any.
What I still need help with: everything mentioned above.
public abstract class ParentClass
{
public string Name { get; set; }
public ParentClass(string Name)
{
this.Name = Name;
}
public enum ChildClasses
{
NoChildClass = 0,
FirstChildClass = 1,
SecondChildClass = 2
}
public virtual ChildClasses TypeOfClass()
{
return ChildClasses.NoChildClass;
}
}
public class FirstChildClass : ParentClass
{
private string _randomvalue;
public string RandomValue { get => _randomvalue; set => _randomvalue = value; }
public FirstChildClass(string Name) : base(Name)
{
}
public void ReturnMessage()
{
Console.WriteLine("This is the FirstChildClass");
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.FirstChildClass;
}
}
public class SecondChildClass : ParentClass
{
private string _randomvalue;
public string RandomValue { get => _randomvalue; set => _randomvalue = value; }
public SecondChildClass(string Name) : base(Name)
{
}
public void ReturnMessage()
{
Console.WriteLine("This is the SecondChildClass");
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.SecondChildClass;
}
}
class MultipleValueTypes
{
public Dictionary<string, List<ParentClass>> ADictionary = new Dictionary<string, List<ParentClass>>();
public void AddObject(string Name, ParentClass variable)
{
if (!ADictionary.ContainsKey(Name))
{
ADictionary.Add(Name, new List<ParentClass>());
}
ADictionary[Name].Add(variable);
}
}
class Program
{
static void Main(string[] args)
{
FirstChildClass FirstObject = new FirstChildClass("FirstObject");
SecondChildClass SecondObject = new SecondChildClass("SecondObject");
MultipleValueTypes TestDictionary = new MultipleValueTypes();
TestDictionary.AddObject("FirstObject", FirstObject);
TestDictionary.AddObject("SecondObject", SecondObject);
if(TestDictionary.ADictionary["FirstObject"].TypeOfClass() == ParentClass.ChildClasses.FirstChildClass) ///List<ParentClass>' does not contain a definition for 'TypeOfClass' and no accessible extension method 'TypeOfClass' accepting a first argument of type 'List<ParentClass>' could be found (are you missing a using directive or an assembly reference?)
{
TestDictionary.ADictionary["FirstObject"] = (FirstChildClass)TestDictionary.ADictionary["FirstObject"]; ///Cannot convert type 'System.Collections.Generic.List<Dictionary.ParentClass>' to 'Dictionary.FirstChildClass
}
}
}
You forgot to use indexer of the list value of the key of the dictionary here:
==> TestDictionary.ADictionary["FirstObject"][0]
Here is your code now refactored too:
class Program
{
static void Main(string[] args)
{
var FirstObject = new FirstChildClass("FirstObject");
var SecondObject = new SecondChildClass("SecondObject");
FirstObject.ReturnMessage();
SecondObject.ReturnMessage();
MultipleValueTypes TestDictionary = new MultipleValueTypes();
TestDictionary.AddObject("FirstObject", FirstObject);
TestDictionary.AddObject("SecondObject", SecondObject);
if ( TestDictionary.ADictionary["FirstObject"][0].TypeOfClass()
== ParentClass.ChildClasses.FirstChildClass )
{
TestDictionary.ADictionary["FirstObject"][0]
= (FirstChildClass)TestDictionary.ADictionary["FirstObject"][0];
}
Console.ReadKey();
}
}
public abstract class ParentClass
{
public string Name { get; set; }
public string RandomValue { get; set; }
public ParentClass(string Name)
{
this.Name = Name;
}
public virtual void ReturnMessage()
{
Console.WriteLine($"This is the {this.GetType().Name} instance");
}
public virtual ChildClasses TypeOfClass()
{
return ChildClasses.NoChildClass;
}
public enum ChildClasses
{
NoChildClass = 0,
FirstChildClass = 1,
SecondChildClass = 2
}
}
public class FirstChildClass : ParentClass
{
public FirstChildClass(string Name)
: base(Name)
{
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.FirstChildClass;
}
}
public class SecondChildClass : ParentClass
{
public SecondChildClass(string Name)
: base(Name)
{
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.SecondChildClass;
}
}
class MultipleValueTypes
{
public readonly Dictionary<string, List<ParentClass>> ADictionary
= new Dictionary<string, List<ParentClass>>();
public void AddObject(string Name, ParentClass variable)
{
if ( !ADictionary.ContainsKey(Name) )
{
ADictionary.Add(Name, new List<ParentClass>());
}
ADictionary[Name].Add(variable);
}
}
If the intention is to cast the whole list from List<ParentClass> to List<FirstChildClass> and List<SecondChildClass>, then Linq is your friend, just use the Cast function:
List<FirstChildClass> firstChildClasses = TestDictionary.ADictionary["FirstObject"]
.Cast<FirstChildClass>().ToList();
List<SecondChildClass> secondChildClasses = TestDictionary.ADictionary["SecondObject"]
.Cast<SecondChildClass>().ToList();
I have class Important and some objects of this class created. I want allow user to choose main object of this class. Have a look at code below:
public class Program
{
public static void Main(string[] args)
{
Important imp1 = new Important("Important 1");
Important imp2 = new Important("Important 2");
Important imp3 = new Important("Important 3");
imp2.SetMostImportant();
Console.Write(Important.MostImportant.Name);
}
public class Important
{
public Important(string name)
{
Name = name;
if(MostImportant == null)
SetMostImportant();
}
public string Name { get; private set; }
public static Important MostImportant { get; private set; }
public void SetMostImportant()
{
MostImportant = this;
}
}
}
Is it good solution? If not, please tell me why not.
Before, to achieve this kind of things I just created boolean field named e.g. IsMainObject and, when I wanted to change main object, I iterated through all objects (or group of object) of specific class except element that I want to be main, and changed boolean to false, in my new candidate I simply set flag to true. Example below:
public class Program
{
public static void Main(string[] args)
{
Important imp1 = new Important("Important 1");
Important imp2 = new Important("Important 2");
Important imp3 = new Important("Important 3");
List<Important> list = new List<Important> { imp1, imp2, imp3 };
foreach(var item in list.Where(x => x.Name != "Important 2"))
{
item.SetMostImportant(false);
}
imp2.SetMostImportant(true);
Console.Write(list.FirstOrDefault(x => x.MostImportant == true).Name);
}
public class Important
{
public Important(string name)
{
Name = name;
}
public string Name { get; private set; }
public bool MostImportant { get; private set; }
public void SetMostImportant(bool val)
{
MostImportant = val;
}
}
}
I don't like this solution because:
I don't know if MostImportant is true for more than one objects without iterating.
I need to write extra-code to handle much more cases.
I don't have possibility to always iterate through all instances of specific class (groups not always are enough).
... and much more, but you got the idea.
public static Important MostImportant { get; private set; }
is a fine solution, and much better than
public bool MostImportant { get; private set; }
It's not uncommon to have a static property of the type that it's inside of when implementing "singleton" classes. I've written code that resembles this:
class MyClass
{
public static MyClass Instance { get; private set; }
public MyClass()
{
if (Instance == null)
{
Instance = this;
}
else
{
throw new Exception("MyClass already instantiated.");
}
}
}
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