I'm trying to make a code that reads the object property of an object before using said ability. In this case, it reads the cooldown of the the ability, then casts the ability if the cooldown equals zero. However, I can't get the code to run without experiencing an error. It will not let me access the property.
public class Pug : Dogs
{
public Pug()
{
ability bark = new Ability();
bark.cooldown = 2;
}
public void PugBark()
{
if (bark.cooldown == 0)//error occurs on this line
{
//He Barks
}
}
}
because of your bark object the only available in the construct function scope.
I think you can try to let bark be a field or property in the Pug class
public class Pug : Dogs , ThingsDogsDo
{
private Ability bark;
public Pug()
{
bark = new Ability();
bark.cooldown = 2;
}
public void PugBark()
{
if (bark.cooldown == 0)//error occurs on this line
{
//He Barks
}
}
}
Related
I've recently been looking into constructors, Im currently trying to pass a object to another class file, The way im doing it is like this:
class Program
{
static void Main(string[] args)
{
Class1 objPls = new Class1();
objPls.nameArray[0] = "jake";
objPls.nameArray[1] = "tom";
objPls.nameArray[2] = "mark";
objPls.nameArray[3] = "ryan";
Echodata form2 = new Echodata(objPls);
}
}
class Class1
{
public string[] nameArray = new string[3];
}
class Echodata
{
public Class1 newobject = new Class1();
public Echodata(Class1 temp)
{
this.newobject = temp;
}
// so now why cant i access newobject.namearray[0] for example?
}
Problem is i cant access the object to get into the array..
What methods of passing objects are there? I was told this is roughly a way to do it and have been experimenting for a while to no avail.
Not sure what it is you cannot do. For example your code with this modification works, or at least compiles.
class echodata
{
public Class1 newobject = new Class1();
public echodata(Class1 temp)
{
this.newobject = temp;
}
// so now why cant i access newobject.namearray[0] for example?
// What kind of access do you want?
public void method1()
{
newobject.nameArray[0] = "Jerry";
}
}
You have an issue where your code will throw an error when trying to set the "ryan" string on the fourth index of the array. You initially set the array to be of length 3.
In your EchoData class you can access the nameArray object without an issue but you must be accessing it within a method or in the constructor. You cannot be manipulating it's content outside of these.
Keep in mind that within your EchoData class you will not see the values you set inside of your Main method.
It's hard to tell since you haven't included a complete, compilable sample, and you haven't explained exactly what "can't access" means (do you get an error? what is it?)
However, my guess is that you are attempting to access the passed in objects fields from the class level based on your code.
ie, you are trying to do this:
class Echodata
{
public Class1 newobject; // you don't need to initialize this
public Echodata(Class1 temp)
{
this.newobject = temp;
}
newobject.newArray[0] = "Can't do this at the class level";
}
You can only access nameArray from within a member method.
class Echodata
{
public Class1 newobject; // you don't need to initialize this
public Echodata(Class1 temp)
{
this.newobject = temp;
}
public void DoSOmething() {
newobject.newArray[0] = "This works just fine";
}
}
I need to determine which object my code is working with at a certain point and write out only the properties specific to that class. I cannot figure out how to do it. I was told I can do it, but I cannot figure it out. Can someone please show me how to determine which object I am working with and write the properties specific to that class only?
I've looked at other questions asked, but am not smart enough to make it fit my example.
Below, I've re-created an example of the code I am working with. I can see all the code, but I am allowed to only work in one method (for this example called "MethodIAmWorkingIn"). Only modifications I am allowed to make are in that method.
public class Program
{
static void Main(string[] args)
{
TestDetailsAndResultsContainer container = new TestDetailsAndResultsContainer();
DerivedClass1 derivedClass1 = new DerivedClass1();
derivedClass1.DerivedClass1Prop1 = "DerivedClass1Prop1";
derivedClass1.DerivedClass1Prop2 = "DerivedClass1Prop2";
DerivedClass2 derivedClass2 = new DerivedClass2();
derivedClass2.DerivedClass2Prop1 = "DerivedClass2Prop1";
derivedClass2.DerivedClass2Prop2 = "DerivedClass2Prop2";
container.TestDetails.Add(derivedClass1);
container.TestDetails.Add(derivedClass2);
TestResult testResult = new TestResult();
testResult.TestResultProp1 = "TestResultProp1";
testResult.TestResultProp2 = "TestResultProp2";
container.Data.Add(testResult);
Program p = new Program();
p.MethodIAmWorkingIn(container);
}
private void MethodIAmWorkingIn(TestDetailsAndResultsContainer container)
{
// I need to see if the container variable holds a DerivedClass1 or DerivedClass2 object.
foreach (var result in container.TestDetails)
{
var classINeedToDetermine = container.TestDetails.FirstOrDefault(m => m.TestDetailsProp1 == result.TestDetailsProp1);
if (classINeedToDetermine is DerivedClass1)
{
classINeedToDetermine = result as DerivedClass1;
}
else if (classINeedToDetermine is DerivedClass2)
{
classINeedToDetermine = result as DerivedClass2;
}
// Now I need to use the classINeedToDetermine object and write its specific properties.
// ???????????????????? I am stuck at this point ??????????????????
// I need to write one or the other below. Can this be done?
// If it is DerivedClass1, I need to write out those properties only.
Console.WriteLine(classINeedToDetermine.DerivedClass1Prop1);
Console.WriteLine(classINeedToDetermine.DerivedClass1Prop2);
// OR
// If it is DerivedClass2, I need to write out those properties only.
Console.WriteLine(classINeedToDetermine.DerivedClass2Prop1);
Console.WriteLine(classINeedToDetermine.DerivedClass2Prop2);
}
}
}
public class TestDetailsAndResultsContainer
{
public TestDetailsAndResultsContainer()
{
this.Data = new List<TestResult>();
this.TestDetails = new List<TestDetails>();
}
public List<TestDetails> TestDetails { get; set; }
public List<TestResult> Data { get; set; }
}
public abstract class TestDetails
{
public string TestDetailsProp1 { get; set; }
public string TestDetailsProp2 { get; set; }
}
public class TestResult
{
public string TestResultProp1 { get; set; }
public string TestResultProp2 { get; set; }
}
public class DerivedClass1 : TestDetails
{
public string DerivedClass1Prop1 { get; set; }
public string DerivedClass1Prop2 { get; set; }
}
public class DerivedClass2 : TestDetails
{
public string DerivedClass2Prop1 { get; set; }
public string DerivedClass2Prop2 { get; set; }
}
The as keyword does not do what you think it does.
Your classINeedToDetermine is a variable of type TestDetails. You can assign a subclass instance to it, but you still cannot access that subclasses specific properties via that variable.
You just need some scope:
if (classINeedToDetermine is DerivedClass1)
{
var derived1 = (DerivedClass1)result;
Console.WriteLine(derived1.DerivedClass1Prop1);
// etc
}
else if (classINeedToDetermine is DerivedClass2)
{
var derived2 = (DerivedClass2)result;
Console.WriteLine(derived2.DerivedClass2Prop1);
// etc
}
This kind of thing is not fun to maintain though.
Another way of doing it would be to use polymorphism: Your TestDetails class could define an abstract method called PrintProperties, and all your subclasses could implement it.
Then you just have to call PrintProperties on every object, without worrying about which subclass they are.
I'm not completely sure on what objects mean what here, but it should be something like this:
foreach(var v in result.GetType().GetProperties())
{
if(v.DeclaringType == result.GetType())
{
Console.WriteLine(v.GetValue(result));
}
}
Again, I wasn't totally clear on your usage of classINeedToDetermine versus result, but you can change those as you see so fit. I chose result as my example since classINeedToDetermine was null by that part of your code.
And by the way, this section of your code is redundant. It should be removed for clarity and efficiency.
if (classINeedToDetermine is DerivedClass1)
{
classINeedToDetermine = result as DerivedClass1;
}
else if (classINeedToDetermine is DerivedClass2)
{
classINeedToDetermine = result as DerivedClass2;
}
Edit:
On the other hand, if performance is more important to you than being scalable (read: if you know or have control over all the classes you'll be dealing with), you could use this is section to do something less, I hate to use this word for this, "generic."
if (classINeedToDetermine is DerivedClass1)
{
var typed = (DerivedClass1)result;
Console.WriteLine(typed.DerivedClass1Prop1);
Console.WriteLine(typed.DerivedClass1Prop2);
}
else if (classINeedToDetermine is DerivedClass2)
{
var typed = (DerivedClass2)result;
Console.WriteLine(typed.DerivedClass2Prop1);
Console.WriteLine(typed.DerivedClass2Prop2);
}
You can use Type.GetProperties to get all Properties for your class. Then you need to get the MethodInfo for the Get method via GetMethod.
Once you have the MethodInfo you can call Invoke, passing in your Derived Class. You can write then write the result to the Console.
I want to be able to store code in a database and then execute it dynamically (using Roslyn). However, I want to be able to (inject?) properties from calling code. See below:
using Roslyn.Scripting.CSharp;
using RoslynMVCTest.Interfaces;
namespace RoslynMVCTest.Services
{
public class MyService
{
private readonly IInjectedService _injectedService;
public MyService(IInjectedService injectedService)
{
_injectedService = injectedService;
}
public bool SomeMethod()
{
string codeString = #"
using RoslynMVCTest.Interfaces;
public class SomethingDoer
{
public IInjectedService InjectedService {get;set;}
public static bool DoSomething()
{
return IInjectedService.SomeOtherMethod();
}
}";
var engine = new ScriptEngine();
var session = engine.CreateSession(_injectedService);
session.AddReference(this.GetType().Assembly);
//How do I set the property in my dynamic code to _injectedService??
var result = session.Execute<bool>("SomethingDoer.DoSomething()");
return result;
}
}
}
I realize there are probably syntax and other issues here, but it's a good representation of what I want to do. Is there a way to do this?
First I'm going to answer your question matching your original code as closely as possible. Second, I'm going to show a far more concise example that might in fact be all that you're after.
You can certainly declare your type as you've done, but a few things will have to be fixed to even get it to make sense.
Your SomethingDoer class declares a non-static InjectedService property, despite the fact that you attempt to consume that property in a static method. I will assume for the sake of discussion that you intended SomethingDoer.DoSomething to be non-static as well and will thus instanatiate that class.
public static bool DoSomething()
To:
public bool DoSomething()
The "sesion" you pass to CreateSession is your actual service. To understand why this won't work, you have to understand what the argument you pass to CreateSession means and what's done with it. What the "session" means is that all the public properties of that object are available to your scripting session as raw identifiers without the need to . reference them on any target. Thus, to get your code working, I've introduced a new class (inner to the main service class for convenience) called Session:
public class Session
{
public IInjectedService InjectedService { get; set; }
}
Furthermore, I've used this new class when invoking CreateSession:
var session = engine.CreateSession(new Session { InjectedService = _injectedService });
What this means is that the property InjectedService is now available to you within your codeString.
Perhaps most importantly, your code codeString is never actually consumed by your code! You seem to have, understandably, conceived of this process as setting up a string for your code, and then imagined that you could then invoke some arbitrary method within it. On the contrary, there is only one block of code. So if you really want to declare a whole class in your script-code, you're still going to have to consume it directly within your script-code as well. This means that the final two lines of your codeString should actually look like:
var somethingDoer = new SomethingDoer { InjectedService = InjectedService };
somethingDoer.DoSomething()";
Here we're instantiating SomethingDoer (because of change 1.) and setting the service property by the implicit InjectedService value provided by the session (because of change 2.).
For completeness, here is the fully working sample code:
namespace RoslynMVCTest.Interfaces
{
public interface IInjectedService
{
bool SomeOtherMethod();
}
}
namespace RoslynMVCTest.Services
{
using RoslynMVCTest.Interfaces;
class Program
{
static void Main(string[] args)
{
Console.WriteLine(new MyService(new InjectedService()).SomeMethod());
Console.ReadLine();
}
}
class InjectedService : IInjectedService
{
public bool SomeOtherMethod()
{
return true;
}
}
public class MyService
{
private readonly IInjectedService _injectedService;
public MyService(IInjectedService injectedService)
{
_injectedService = injectedService;
}
public class Session
{
public IInjectedService InjectedService { get; set; }
}
public bool SomeMethod()
{
string codeString = #"
using RoslynMVCTest.Interfaces;
public class SomethingDoer
{
public IInjectedService InjectedService { get; set; }
public bool DoSomething()
{
return InjectedService.SomeOtherMethod();
}
}
var somethingDoer = new SomethingDoer { InjectedService = InjectedService };
somethingDoer.DoSomething()";
var engine = new ScriptEngine();
var session = engine.CreateSession(new Session { InjectedService = _injectedService });
session.AddReference(this.GetType().Assembly);
//How do I set the property in my dynamic code to _injectedService??
var result = session.Execute<bool>(codeString);
return result;
}
}
}
Alternative Approach
If all you want to do is allow your script to run some code that interacts with your service, you can see how this is actually extremely trivial given all the points made above. Thus to concisely express what might be the intent of your original code, all you'd have to do is:
var result = session.Execute<bool>("InjectedService.SomeOtherMethod()");
The code passed in here is simply the body of the service method in the long-winded first example. Quite possibly this is all you need or want.
I'm creating a child object from a parent object. So the scenario is that I have an object and a child object which adds a distance property for scenarios where I want to search. I've chosen to use inheritance as my UI works equivalently with either a search object or a list of objects not the result of a location search. So in this case inheritance seems a sensible choice.
As present I need to generate a new object MyObjectSearch from an instance of MyObject. At present I'm doing this in the constructor manually by setting properties one by one. I could use reflection but this would be slow. Is there a better way of achieving this kind of object enhancement?
Hopefully my code below illustrates the scenario.
public class MyObject {
// Some properties and a location.
}
public class MyObjectSearch : MyObject {
public double Distance { get; set; }
public MyObjectSearch(MyObject obj) {
base.Prop1 = obj.Prop1;
base.Prop2 = obj.Prop2;
}
}
And my search function:
public List<MyObjectSearch> DoSearch(Location loc) {
var myObjectSearchList = new List<MyObjectSearch>();
foreach (var object in myObjectList) {
var distance = getDistance();
var myObjectSearch = new MyObjectSearch(object);
myObjectSearch.Distance = distance;
myObjectSearchList.add(myObjectSearch);
}
return myObjectSearchList;
}
The base class needs to define a copy constructor:
public class MyObject
{
protected MyObject(MyObject other)
{
this.Prop1=other.Prop1;
this.Prop2=other.Prop2;
}
public object Prop1 { get; set; }
public object Prop2 { get; set; }
}
public class MyObjectSearch : MyObject
{
public double Distance { get; set; }
public MyObjectSearch(MyObject obj)
: base(obj)
{
this.Distance=0;
}
public MyObjectSearch(MyObjectSearch other)
: base(other)
{
this.Distance=other.Distance;
}
}
This way the setting of properties is handled for all derived classes by the base class.
You can use reflection to copy properties.
public class ChildClass : ParentClass
{
public ChildClass(ParentClass ch)
{
foreach (var prop in ch.GetType().GetProperties())
{
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(ch, null), null);
}
}
}
There is no easy way to do this, unfortunately. As you said, you would either have to use reflection, or create a "Clone" method that would generate a new child object using a parent object as input, like so:
public class MyObjectSearch : MyObject {
// Other code
public static MyObjectSearch CloneFromMyObject(MyObject obj)
{
var newObj = new MyObjectSearch();
// Copy properties here
obj.Prop1 = newObj.Prop1;
return newObj;
}
}
No matter what, you're either going to end up writing reflection code (which is slow), or writing each property out by hand. It all depends on whether or not you want maintainability (reflection) or speed (manual property copy).
A generic solution would be to serialize it to json and back. In the json-string is no information about the class name from which it was serialized.
Most people do this in javascript.
As you see it works well for pocco objects but i don't guarantee that it works in every complex case. But it does event for not-inherited classes when the properties are matched.
using Newtonsoft.Json;
namespace CastParentToChild
{
public class Program
{
public static void Main(string[] args)
{
var p = new parent();
p.a=111;
var s = JsonConvert.SerializeObject(p);
var c1 = JsonConvert.DeserializeObject<child1>(s);
var c2 = JsonConvert.DeserializeObject<child2>(s);
var foreigner = JsonConvert.DeserializeObject<NoFamily>(s);
bool allWorks = p.a == c1.a && p.a == c2.a && p.a == foreigner.a;
//Your code goes here
Console.WriteLine("Is convertable: "+allWorks + c2.b);
}
}
public class parent{
public int a;
}
public class child1 : parent{
public int b=12345;
}
public class child2 : child1{
}
public class NoFamily{
public int a;
public int b = 99999;
}
// Is not Deserializeable because
// Error 'NoFamily2' does not contain a definition for 'a' and no extension method 'a' accepting a first argument of type 'NoFamily2' could be found (are you missing a using directive or an assembly reference?)
public class NoFamily2{
public int b;
}
}
If a shallow copy is enough, you can use the MemberwiseClone method.
Example:
MyObject shallowClone = (MyObject)original.MemberwiseClone();
If you need a deep copy, you can serialize/deserialize like this: https://stackoverflow.com/a/78612/1105687
An example (assuming you write an extension method as suggested in that answer, and you call it DeepClone)
MyObject deepClone = original.DeepClone();
I first came accros this question when I was looking for doing this.
If you are able to work with C# 9 and record-classes. You only have to create a new constructor in the sub-class taking in a base class object and hand it over to the subclass:
public record MyObject {
...
}
public record MyObjectSearch :MyObject
{
public MyObjectSearch(MyObject parent) : base(parent) { }
...
}
Then you can create the child object like this:
MyObject parent = new();
MyObjectSearch m = new MyObjectSearch(parentObj) { Distance = 1.1};
Credits to https://stackoverflow.com/a/64573044/2582968
Seems natural for the base object to have constructor with parameters for its properties:
public class MyObject
{
public MyObject(prop1, prop2, ...)
{
this.Prop1 = prop1;
this.Prop2 = prop2;
}
}
So then, in your descendant object you can have:
public MyObjectSearch(MyObject obj)
:base(obj.Prop1, obj.Prop2)
This reduces duplication related to assignments. You could use reflection to automatically copy all properties, but this way seems more readable.
Note also, that if your classes have so much properties that you're thinking about automatizing of copying of the properties, then they are likely to violate the Single Responsibility Principle, and you should rather consider changing your design.
There are libraries to handle this; but if you just want a quick implementation in a few places, I would definitely go for a "copy constructor" as previously suggested.
One interesting point not mentioned is that if an object is a subclass, then it can access the child's private variables from the within the parent!
So, on the parent add a CloneIntoChild method. In my example:
Order is the parent class
OrderSnapshot is the child class
_bestPrice is a non-readonly private member on Order. But Order can set it for OrderSnapshot.
Example:
public OrderSnapshot CloneIntoChild()
{
OrderSnapshot sn = new OrderSnapshot()
{
_bestPrice = this._bestPrice,
_closed = this._closed,
_opened = this._opened,
_state = this._state
};
return sn;
}
NOTE: Readonly member variables MUST be set in the constructor, so you will have to use the child constructor to set these...
Although I don't like "up-sizing" generally, I use this approach a lot for analytic snapshots...
In Excel object model 'Thisworkbook' is a class that has 'Worksheets' class in it and can be overloaded with index or by sheet name. Moreover, 'Worksheets' class also has some properties/methods that can be called with/without calling the constructor (default).
E.g. MsgBox ThisWorkbook.Worksheets(1).Name '<-- by (int)
E.g. MsgBox ThisWorkbook.Worksheets("Sheet1").Name '<- by (string)
E.g. Msgbox Thisworkbook.Worksheets.Count '<- 'count property
How can I create such class in C# that has another class in it and can be overloaded?
I have tried creating a public variable of the 2nd class in the 1st class but I can only call default constructor (or other - but just one at a time)
class A
{
public B b = new B(); // <-- this is 1st constructor but how to overload ?
}
class B
{
public B() // Default Constructor
{
}
public B(int i) // Constructor 2
{
}
public B(string s) // Constructor 3
{
}
public int Count // Property
{
get { return 0; }
}
}
//------------------------------------------------------------
class Main()
{
A a = new A();
a.b.Count(); // <-- THIS WORKS
// a.b(1).Name; <-- HOW TO, USING THE SAME CLASS?
// a.b("A").Name; <-- HOW TO, USING THE SAME CLASS?
}
I know that I have not created an object array - 1 or "A" that can be returned in this example, but I just need the concept (you got it right?). I have also seen few examples using List but I really want to know how I can achieve such object hierarchy in C#... (please excuse me if this is a wrong question).
You're misunderstanding operators.
What you're seeing is the indexing operator defined on the Worksheets class.
In C#, that would be called as a.b[1] or a.b["2"].
You define it like this:
public SomeType this[int index] { get { ... } }
public SomeType this[string index] { get { ... } }