Using a string variable to set a 'Class = new <string of Class()>' - c#

I have a three polymorphed classes. Based on user input the class should be set to that user's input. So the child class is decided by a user, and should make for 'class = new inputClass'. The snippet of code looks like:
public void characterGeneration(string classSelected)
{
foreach (string classInList in classes.ClassList)
{
if (classSelected == classInList)
{
PlayerOneStats = new Mage();
}
}
PlayerOneStats.generateStats();
}
Where it says PlayerOneStats = new Mage();, I want the Mage() to be the user input.
I've looked at Activator, Assembly, using Type, trying to cast over to the parent of GenerateStats, but nothing works. I've found many people saying it works, and one link that says it doesn't work. Can somebody please clear this up for me? Thank you very much!

Are you sure Activator doesn't work? Activator.CreateInstace("assembly-name", "type-name") seems like exactly what you want. What doesn't work?

What is the base class of Mage (and the other classes a user can select)? You should be able to do this:
public void characterGeneration(string classSelected)
{
foreach (string classInList in classes.ClassList)
{
if (classSelected == classInList)
{
PlayerOneStats = (GenerateStats)Assembly.GetExecutingAssembly().CreateInstance("YourNamespace." + classSelected);
break;
}
}
PlayerOneStats.generateStats();
}

Make sure that you include the namespace the type you want is contained in and this should work for you:
string classSelected = "testCode.Mage";
var player = Activator.CreateInstance(Type.GetType(classSelected));
Since Activator.CreateInstance() returns an object you will have to cast - in your case it would make sense to cast to an interface that all your player classes implement:
var player = (IPlayerCharacter) Activator.CreateInstance(Type.GetType(classSelected));

Related

Creating a class with a generic csv reader via a method

As a headsup, I'm new to stackoverflow so please do tell me if I'm just bad at searching for a solution.
I have a class library that's able to read csv files depending on the public members of a class and then assign them. However, I don't know a way to avoid a long switch or if else when I want to call/invoke the method.
Here's how I currently use it:
public class DataSetup
{
List<object> ObjList = new List<object>();
public DataSetup(string file)
{
switch (file)
{
case "Persons.csv":
AssignCsvData<Person>(file);
break;
case "Address.csv":
AssignCsvData<Address>(file);
break;
}
}
public void AssignCsvData<T>(string file) where T : CsvableBase, new()
{
var cr = new CsvReader<T>();
var csvObjs = cr.Read(file);
foreach (var obj in csvObjs)
{
ObjList.Add(obj);
}
}
}
The switch is not "done", since I'm hoping for a better way.
So is there a way to call the AssignCsvData without the switch?
So far I've tried taking a type as a parameter for the constructor, but I can't use it as a type when it's a variable.
If the name of the file always represents a class. In your case there is a mismatch between Persons.csv and Person, but say they do match then the following could work using reflection, rather than a switch statement:
var type = Type.GetType(Path.GetFileNameWithoutExtension(file));
var method = typeof(Processor)
.GetMethod("AssignCsvData")
.MakeGenericMethod(type);
method.Invoke(new Processor(), file);
NOTE: If you'd like to test this in LinqPad, don't forget to use the "UserQuery+" namespace to get the type. i.e.:
var type = Type.GetType($"UserQuery+{Path.GetFileNameWithoutExtension(file)}");

How to know whether given is variable of specific class?

I want to know whether passed object is actually reference of variable of specific class or not.
Consider below structure of some class 'ClassA':
public classA
{
string variable1;
int variable2;
method1(ref variable1);
}
Now if in class that contains implementation of method1(Obj object1), I want to check that 'object1' is which variable of specific 'ClassA' ?
Because I want to check in if condition like if object1 is variable1 of ClassA then //to proceed with logic....
Please provide a small example for the same.
The closest you could get to this in safe code is using expressions, but honestly you probably don't want to do this. It'd be a nightmare to try and debug, and there's probably another way to go about it. For example, is there any reason variable1 can't be of a specific type?
Now that I've spoken reason, the approach using expressions goes something like this (This is from a debugging helper, I would never use this approach in anything remotely serious. Note: A lot of exception handling and other code is stripped from this, also note how ugly and hackish it looks, that's all why you really shouldn't do this):
public static void DoStuffWithParameter<T>(Expression<Func<T>> paramExpression)
{
if (paramExpression == null) throw new ArgumentNullException("paramExpression");
var body = ((MemberExpression)paramExpression.Body);
var paramName = body.Member.Name;
var param = ((FieldInfo)body.Member)
.GetValue(((ConstantExpression)body.Expression).Value);
var declaringType = param.DeclaringType;
var paramValue = paramExpression
.Compile()
.Invoke();
if(declaringType.Equals(typeof(ClassA)))
{
//do stuff
}
}
To use that you'd use something like:
DoStuffWithParameter(()=>myClass.VarA);
I found solution. The simplest way to do this is to pass object of sender in method1 and proceed, like below.
method1(Object sender, ref Object var)
{
if(sender is classA)
{
classA senderObj= (classA) sender;
if((string)var == senderObj.variable1)
{
// Logic for variable1
}
else if((int)var == senderObj.variable2)
{
// Logic for variable2
}
. . .
}
}

The following throws 'is a Method but treated like a type'

The most confusing error I have ever seen in ASP. I have done method calls like this before, and have no issue in other spots of my code.
First of all the class:
namespace LocApp.Helpers.Classes.LocationHelper
{
public class QueryHelper
{
private LocAppContext db = new LocAppContext();
public static IEnumerable<Service> getAllService()
{
using (var db = new LocAppContext())
{
var service = db.Locations.Include(s => s.LocationAssignment);
var serv = (from s in db.Services
where s.active == true
select s).ToList();
return serv;
}
}
}
}
Pretty easy to understand whats going on. So lets call the method:
IEnumerable<LocApp.Models.Service> Service = new LocApp.Helpers.Classes.LocationHelper.QueryHelper.getAllService(Model.id);
getAllServices(Model.id) is throwing the error "is a method but treated like a type" , um no its not be treated like a type....
whats going on?
Well it's exactly as the error message says. getAllService() is a method:
public static IEnumerable<Service> getAllService()
But you're trying to use it as if it were a type with a constructor:
Service = new LocApp.Helpers.Classes.LocationHelper.QueryHelper.getAllService(...)
The new part is the mistake here. You don't want to call a constructor, you just want to call a method. It's a static method, so you don't need an instance - you can just use:
Service = LocApp.Helpers.Classes.LocationHelper.QueryHelper.getAllService(...)
Note that if you have appropriate using directives, follow .NET naming conventions and take care about singular/plural names, your code will be easier to follow:
var services = QueryHelper.GetAllServices(...);
Do you not simply mean:
IEnumerable<LocApp.Models.Service> Service = LocApp.Helpers.Classes.LocationHelper.QueryHelper.getAllService();
Get rid of the new bit, essentially, and that method doesn't take any parameters either - I'd assume you'd run into that problem after you removed the new bit.
Your getAllService method doesn't take any arguments, so you should call it without. Also it is a static method so don't use the new keyword:
IEnumerable<LocApp.Models.Service> Service = LocApp.Helpers.Classes.LocationHelper.QueryHelper.getAllService();

"Use of unassigned local variable" error with an Interface

I'm having trouble with some syntax. I'm not really familiar with interfaces so please excuse my ignorance.
VS2010 is giving me an error at... application.Name = System.AppDomain.CurrentDomain.FriendlyName;
public static void AddApplication(string applicationName = null, string processImageFileName = null)
{
INetFwAuthorizedApplications applications;
INetFwAuthorizedApplication application;
if(applicationName == null)
{
application.Name = System.AppDomain.CurrentDomain.FriendlyName;/*set the name of the application */
}
else
{
application.Name = applicationName;/*set the name of the application */
}
if (processImageFileName == null)
{
application.ProcessImageFileName = System.Reflection.Assembly.GetExecutingAssembly().Location; /* set this property to the location of the executable file of the application*/
}
else
{
application.ProcessImageFileName = processImageFileName; /* set this property to the location of the executable file of the application*/
}
application.Enabled = true; //enable it
/*now add this application to AuthorizedApplications collection */
Type NetFwMgrType = Type.GetTypeFromProgID("HNetCfg.FwMgr", false);
INetFwMgr mgr = (INetFwMgr)Activator.CreateInstance(NetFwMgrType);
applications = (INetFwAuthorizedApplications)mgr.LocalPolicy.CurrentProfile.AuthorizedApplications;
applications.Add(application);
}
I can make that error go away by setting application to null but that causes a run-time null reference error.
Edit:
Here's where I'm adapting the code from. I hope it gives more context
http://blogs.msdn.com/b/securitytools/archive/2009/08/21/automating-windows-firewall-settings-with-c.aspx
You never initialize
application
before using it here:
application.Name = System.AppDomain.CurrentDomain.FriendlyName;
The variable application is defined as:
INetFwAuthorizedApplication application
You need to assign an instance of a class that implements the interface INetFwAuthorizedApplication.
Somewhere there must be one (or probably more) classes in your project that look something like this:
public class SomeClass : INetFwAuthorizedApplication
{
// ...
}
public class AnotherClass : INetFwAuthorizedApplication
{
// ...
}
You need to determine what class you should use (SomeClass, AnotherClass) then assign an appropriate object, e.g. like this:
INetFwAuthorizedApplication application = new SomeClass();
Interfaces are used to describe what an object does, not what it is specifically. To put into "real world" terms, an interface might be like:
ISmallerThanABreadbox with a FitIntoBreadbox() method. I can't ask you to give me "the smaller than a breadbox" ... as that doesn't make any sense. I can only ask you to give me something that "IS smaller than a breadbox". You have to come up with your own object that makes sense to have the interface on it. An apple is smaller than a breadbox, so if you have a breadbox that only holds items smaller than it, an apple is a good candidate for the ISmallerThanABreadbox interface.
Another example is IGraspable with a Hold() method and FitsInPocket bool property. You can ask to be given something that IS graspable that may or may not fit in your pocket, but you can't ask for "the graspable".
Hope that helps...

LINQ to Entities - Best way to accomplish this?

OK, I am mostly a LAMP developer so I am new to the entity framework. However, I am familiar with the basics in LINQ and have generated a entity model from my DB. Now here is my requirement:
I have a datagrid on a WinForm that will be refreshed from a data source on a remote server every few seconds as changes to the dataset are made from other sources. Obviously, I'd like to construct a lambda expression to get the right anonymous type to satisfy the columns that needs to be shown in my datagrid. I have done this and here is the result (I'm using a custom datagrid control, btw):
And my code thus far:
Models.dataEntities objDB = new Models.dataEntities();
var vans = from v in objDB.vans
select v;
gcVans.DataSource = vans;
OK, so now I have my basic data set. One problem I had is that the "Status" column will show a calculated string based on several parameters in the data set. I added this to my entities via a partial class. As you can see in the screenshot, this is working correctly:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WindowsFormsApplication1.Models {
public partial class van {
public string van_status {
get {
if (this.is_offline == 1) {
return "Offline";
} else if (this.is_prayer_room == 1) {
return "In Prayer Room";
} else {
return "TODO: Create statuses";
}
}
}
}
}
This added property works fine. However, the second I try to project the status in an anonymous type so I can also retrieve the school name, I get an error:
Models.dataEntities objDB = new Models.dataEntities();
var vans = from v in objDB.vans
select new {
van_name = v.van_name,
school_name = v.school.school_name,
capacity = v.capacity,
phone = v.phone,
van_status = v.van_status
};
gcVans.DataSource = vans;
So, I have two questions:
1) If I cannot use computed properties of my partial classes in LINQ projections, how am I supposed to show my computed string in my datagrid?
2) Am I even approaching this correctly? When I resolve #1, how would I refresh this data (ie during a timer fire event)? Would I simply call objDB.refresh() and then tell my datagrid to update from the datasource? Does calling that method actually run the lambda expression above or does it load everything from the DB?
Thanks for any assistance with this. Also, if you have any best practices to share that would be awesome! I hope I explained this as thoroughly as you need to provide assistance.
1) Instead of modifying your EF object with a partial class you could always create your own class that contains your read only property van_status. The code you've got would be nearly identical:
Models.dataEntities objDB = new Models.dataEntities();
gcVans.DataSource = from v in objDB.vans
select new DisplayVan {
van_name = v.van_name,
school_name = v.school.school_name,
capacity = v.capacity,
phone = v.phone,
};
The van_status property, since it's read-only, will not need to be specified in the query.
2) I'm more a web developer than a desktop developer so I'll give you my take on how to refresh the grid (it may not be the preferred methodology for fat clients)...
I'm reluctant to trust .Refresh() methods and hope all works to maximal efficiency and work properly. Instead, encapsulate the code from #1 in a method of your own and invoke it from your timer event firing (or however you choose to implement the periodic refresh).
Another good option would be to create an extension method.
Here is a simple example:
using System;
namespace WindowsFormsApplication1 {
static class Program {
[STAThread]
static void Main() {
Van van = new Van();
string status = van.GetStatus();
}
}
public static class VanExtension {
public static string GetStatus(this Van van) {
if(van.is_offline == 1) {
return "Offline";
}
else if(van.is_prayer_room == 1) {
return "In Prayer Room";
}
return "TODO: Create statuses";
}
}
public class Van {
public int is_offline { get; set; }
public int is_prayer_room { get; set; }
}
}
Be sure to put this extension class in the same namespace as the entity class.

Categories