c# - Initialize List<> from another class - c#

I have defined a class which has List<>. I have shortened my Code. It is too large. There are too many List<>& in Method1() there is lots of code. Here is my code :-
public class Time : ITime
{
public List<Table1> Setts1 = new List<Table1>();
public List<Tabl2> Setts2 = new List<Table2>();
public void LoadSettings1(int companyId)
{
Setts1 = ctx.tblSett1.Where(a => a.CompanyId == companyId).Select(a => a).ToList();
}
public double Method1()
{
var data = Setts1.Where(m => m.SetType == "TYPE1").Select(m => m.Value1).FirstOrDefault();
......
......
}
}
I want to use Method1() in another class. My issue is Setts1 which is preloaded in the Time Class. So when it is used in within the Time class it has Records. But when i call it from another class obviously Setts1 will have no records. I tried to initialize it from another class like this :-
public class Class
{
.....
Time cls = new Time();
cls.Setts1 = ....;
cls.Method1();
}
But Setts1 shows no records when in Method1. How to initialize the List<> from another class?

Exposing field members of a class, outside of the class is not a good practice. So I recommend using properties like this:
//Mark the field member as private
private List<Table1> _Setts1 = new List<Table1>();
//Use Property to access the field outside of the class
public List<Table1> Setts1
{
get
{
if (_Setts1==null || _Setts1.Count()==0) //or any other logic you need
{
//Initialize the field memeber
_Setts1 = ctx.tblSett1.Where(a => a.CompanyId == companyId).Select(a => a).ToList();
}
return _Setts1
}
}
This way you can forget about methods like LoadSettings1 and it doesn't matter whether you use the Setts property inside the class or outside, it will be initialized at the right time.

You have to call 'LoadSettings1(int companyId)'. This is the method which brings the records and populates your 'List'.
public class Class
{
.....
Time cls = new Time();
cls.LoadSettings1(1);
cls.Setts1 = ....;
cls.Method1();
}

public class Something
{
private Time cls = new Time();
public Something(int companyId)
{
cls.LoadSettings1(companyId);
}
public void CallMethod1()
{
cls.Method1();
}
}
Something like this? Using constructor for your "other class" to LoadSettings.

cls.Setts1 = ....;
Actually I don't see how your code would not work, even if as Hossein said, it's bad practice. Look into how you're setting cls.Setts1 (the .... part). That's most probably the culprit

Related

Add singleton to IServiceCollection dynamically in a loop

Hi I have an interface which is implemented by multiple classes.
public interface IHuman
{
void Talk();
}
public class AdultHuman
{
public void Talk()
{
Console.Writeline("Hi");
}
}
public class BabyHuman
{
public void Talk()
{
Console.Writeline("Babble");
}
}
public enum HumanEnums
{
Adult,
Baby
}
Currently in my startup add on I have
services.AddSingleton<AdultHuman>();
services.AddSingleton<BabyHuman>();
We are constantly adding different implementations of IHumans so I would like my start up add on to be dynamic to add the singletons with a forloop looping through the values of the HumanEnums so it would look like this
var enumTypes = Enum.GetValues(typeof(ActionTypes));
foreach(var enum in enumTypes)
{
var type = typeof(IHuman);
// namespace + name of class i.e MyProgram.Humans.BabyHuman
var typeName = $"{type.Namespace}.{action}Human";
var t = Type.GetType(typeName, true);
services.AddSingleton< --something here-- >();
}
How would I achieve this?
P.S. Also it would be helpful if instead of looping through the enums, I could find all implementations of IHuman and loop through that.
Thanks guys I was able to solve it with your help! I didnt realize that you could add single with types instead of classes. So I used AddSingleton(typeof(Adult)); instead of AddSingleton();
var humanTypes = typeof(IHuman).
GetTypeInfo().Assembly.DefinedTypes
.Where(t => typeof(IHuman).GetTypeInfo().IsAssignableFrom(t.AsType()) && t.IsClass)
.Select(p => p.AsType());
foreach(var humanType in humanTypes )
{
services.AddSingleton(humanType);
}

Setting a field of a class's instance with reflection

I have the following issue related to reflection , I have a method which looks like this :
[TestMethod()]
public void steamAccess()
{
testRead = new TestRead();
SteamMap a = new SteamMap();
// Preparing the parameters of the CSV actions
a.writeMessageParams.UIItemEditText = TestContext.DataRow["SearchQuery"].ToString();
//Read and Execute the TestMethod
testRead.Read(a, TestContext);
}
This is a CodedUITest, SteamMap is a class (uiTest map).
WriteMessageParams is a class, actually the real method is WriteMessage but this class allows me to override the string that gets used into my tests by the WriteMessage method, and I plan to make this part of the code more dynamically in the Read method. :
a.writeMessageParams.UIItemEditText = TestContext.DataRow["SearchQuery"].ToString();
My problem happens in testRead.Read context as follows :
When this method is running I have access to all actions from the respective instance ( a in my case ) and if they are supposed to have to use a a.writeMessageParams.UIItemEditText context I know it, how I get the info isn't the problem, the problem is how to make the previously mentioned code to run dynamically as I have tried :
/* I've done this because I know that each method that is supposed to end up with Params, for example a method called WriteMessage, it's class is called WriteMessageParams*/
public void Read(object obj, TestContext testContext)
{
//simplified code
//trying to access/get to the current instance's WriteMessageParam class
Object testObj = obj.GetType().GetMember(subMethod.Code + "Param");
//null
MessageBox.Show(testObj.GetType().ToString());
// trying to access the UIItemEditText field ( which is declared as public) and modify it accordingly
FieldInfo subMethodField = testObj.GetType().GetField("UIItemEditText");
subMethodField.SetValue(testObj,testContext.DataRow[subMethod.CsvColumn].ToString());
}
I've had a read over this article and tried few things
https://msdn.microsoft.com/en-us/library/6z33zd7h%28v=vs.110%29.aspx
My problem is that I have the object of an instance and I try to access this object's class and modify that class's field .
I'd appreciate any help,
Thanks
Edit 1:
This is how the class I'm trying to access looks like :
public partial class SteamMap
{ //simplified to what classes/methods interest me
public virtual writeMessageParams writeMessageParams
{
get
{
if ((this.mwriteMessageParams == null))
{
this.mwriteMessageParams = new writeMessageParams();
}
return this.mwriteMessageParams;
}
}
public class writeMessageParams
{
#region Fields
/// <summary>
/// Type 'test' in text box
/// </summary>
public string UIItemEditText = "test";
#endregion
}
}
Edit 2 - I've tried by using GetNestedType, still no success....
Object testObj = obj.GetType().GetNestedType("writeMessageParams",BindingFlags.Public);
MessageBox.Show(testObj.GetType().ToString());
If I understand you, you have a class like
public partial class SteamMap
{
private writeMessageParams mwriteMessageParams ;
public virtual writeMessageParams writeMessageParams1
{
get
{
if ((this.mwriteMessageParams == null))
{
this.mwriteMessageParams = new writeMessageParams();
}
return this.mwriteMessageParams;
}
}
public class writeMessageParams
{
public string UIItemEditText = "test";
}
}
(your code doesn't compile because you have writeMessageParams both as the class and the property, so I have changed the property to writeMessageParams1)
And you want to change UIItemEditText, which you can do like
public void UpdateUI(object obj, string newValue)
{
var property = obj.GetType().GetProperty("writeMessageParams1");
var writeMessageParams1 = property.GetValue(obj);
var uiFld = wp.GetType().GetField("UIItemEditText");
uiFld.SetValue(writeMessageParams1, newValue);
}
which can be called like
SteamMap sm = new SteamMap();
Write(sm, "Hello");
The key is to use .GetProperty for the property and .GetField for the field.

How to add a class property to a list of instances

I'm newbie in C#. Perhaps this is too simply to resolve but I'm really away of the solution.
I have this class:
public class TestSetups : TabelaCtset
{
public IList<TabelaCtsca> ValSetup { get { return m_valsetup; } }
private static List<TabelaCtsca> m_valsetup;
/// Constructor
public TestSetups(IDefinitionList dlist)
: base(dlist)
{
m_valsetup = new List<TabelaCtsca>();
}
}
I have another class called TestCase
public class TestCase : TabelaCttes
{
public IList<TestSetups> Setups { get { return m_setups; } }
private List<TestSetups> m_setups;
...
testcase.m_setups = new List<TestSetups>();
defs = gdl.GetDefinitions(testcase);
while (defs.MoveNext())
{
TestSetups testsetup = new TestSetups(defs);
IDefinitionList valsetup = gdl.GetDefinitions(testsetup);
{
TabelaCtsca ctsca = new TabelaCtsca(valsetup);
testsetup.ValSetup.Add(ctsca);
}
testcase.Setups.Add(testsetup);
}
return testcase;
...
}
I want to put all ctsca values in a ValSetup list. All works fine, except this line testcase.Setups.Add(testsetup);: I have the the properties of TestSetups class but my ValSetup property is always empty, when my while goes to another iteration.
Sorry for this weird explanation. I'm able to explain in more detail.
Update: In this situation, I store in each TestSetup just the last ValSetup value and not all the ValSetup of each TestSetup.
You've made m_valsetup a static property, but you're re-initializing every time you create a new instance of TestSetups. If you want it to be a shared list across all instances of TestSetups, then you could use a property initializer like this:
private static List<TabelaCtsca> m_valsetup = new List<TabelaCtsca>();
And remove the initialization of it in the constructor.
If you didn't intend for the list to be shared, then just remove the static keyword from its definition.

Creating common class objects based on class name and use it

I have the same code logic used across different class objects.
For ex:
var matchingTypes = from matchType in order.Contacts
select matchType;
var matchingTypes = from matchType in customer.Contacts
select matchType;
Instead of writing duplicate lines of code, i would like to pass order, customer class names and get Contacts through it, so that the above code will look like (we are using LINQ in our code)
var matchingTypes = from matchType in objectElement.Contacts
select matchType;
The stuff i tried is passed an object parameter
GetData(object objectElement) // method consuming an object parameter.
var objectOrder= objectElement as Orders;
var objectCustomer= objectElement as Customers;
if(objectOrder!=null)
{
objectElement = (Orders) objectOrder; //type
}
if(objectCustomer !=null)
{
objectElement = (Customers) objectCustomer;
}
By doing so, i am repeating my code, which i would like to avoid, any suggestions/ideas? thanks.
I would like to use objectElement and assign only once, so that i can call like this as shown below
var matchingTypes = from matchType in objectElement.Contacts
select matchType;
An interface would be the preferred way to do this, but you could also use dynamic to duck type a method:
public IEnumerable<Contact> GetContacts(dynamic yourObject)
{
return yourObject.Contacts;
}
Note this will not give you a compile error if you call it with something that doesn't have a property called Contacts of type IEnumerable<Contact> but will instead give you a runtime error.
Or you don't even actually need a method, you could just do this:
var matchedTypes = ((dynamic)yourObject).Contacts as IEnumerable<Contact>;
Interfaces would be a safer bet, but are a little tricky with generate entity framework classes. But you can do them becuase they are generated as partial classes. So you can do something like this:
public interface IHaveContacts
{
public IEnumerable<Contact> Contacts { get; }
}
and then:
public partial class Orders : IHaveContacts
{
// should need to do anything since the auto-genrated Contacts property
// will satisfy the interface
}
public partial class Customers : IHaveContacts
{
// ditto
}
And now you can do:
var matchedTypes = ((IHaveContacts)yourObject).Contacts;
Or, if you really, really must (which you don't):
var matchedTypes = from matchType in ((IHaveContacts)yourObject).Contacts
select matchType;
Create an interface IContactsContainer:
public interface IContactsContainer
{
public YourContactType Contacts{get;set;}
}
Then your customer and order classes can implement it:
public class Customers : IContactsContainer
{
public YourContactType Contacts {get;set;}
....
}
public class Orders: IContactsContainer
{
public YourContactType Contacts {get;set;}
....
}
After that in your method you can use:
IContactsContainer objectElement = yourOrderObject;

Returning data from one method to another within a class

Thanks for help with the question I just submitted about anonymous classes. Now I understand more. Here's a bit more of an example:
public class abc {
public xx doAction() {
return ( new { ID = 5, Name= "Dave" } );
}
public void doStart() {
var a = doAction();
var b = a.ID;
var c = a.Name;
}
}
So am I correct in saying that the most ideal way to do this would be to declare a class XYX and use it like this:
public class abc {
public XYZ doAction() {
return ( new XYZ { ID = 5, Name= "Dave" } );
}
public void doStart() {
var a = doAction();
var b = a.ID;
var c = a.Name;
}
}
The class would be only used for this one data transfer between the two methods.
I think you meant: return new XYZ(5, "Dave")
Anyways, your solution is okay but there is no reason to create a new class simply to share data. You can use a hashtable/array/dictionary or whatever class suits you best to share data. If you want to do something special with the XYZ class, or it has methods you wish to call from it, then you would have to create a new class XYZ and return it. Though, if you just want to share data, use a data structure that's already available to your use.
That would work yes. If it is the most ideal or not is hard to say. Since you are using the variables "ID" and "Name" it kinda indicates that you are working with domain objects from a database, and if so, you will probably need the class for a lot more than just this one method.
What about the class ABC? What kind of class is that? Because you could also do this:
public class abc{
private int _id;
private string _name;
public void DoAction(){
_id = 5;
_name = "Dave";
}
public void DoStart(){
var b = _id;
var c = _name;
}
}
But remember to use proper naming for your classes, so you have an idea of what they are used for.
Yes, though if your class has trivial properties you can consider using existing .Net classes:
1) You can consider using System.Tuple (.Net 4.0) but you will not have good property names anymore:
var result = Tuple.Create(5, "Dave");
int id = result.Item1;
string name = result.Item2;
2) You can use KeyValuePair if it is applicable:
var result = new KeyValuePair<int, string>(5, "Dave");
int id = result.Key;
string name= result.Value;

Categories