I have the following class and my question lies with it's GetComponent function
class GameObject
{
private List<GameComponent> _components = new List<GameComponent>();
public void AddComponent(GameComponent component)
void RemoveComponent(string name)
public T GetComponent<T>(string name) where T : GameComponent
}
class GameComponent
{
public string Name { get; set; }
}
So in GetComponent i want to get the component identified by name and return it as T.
So i would call
NavigationComponent navigation = gameObject.GetComponent<NavigationComponent>("navigation");
where NavigationComponent would be a subclass of GameComponent
Since each NavigationComponent instance is only ever going to have the same name, "navigation", i am pondering if i can do something to simplify the GetComponent to the following
NavigationComponent navigation = gameObject.GetComponent<NavigationComponent>();
Thanks in advance.
Update 1
Well i should mention that the GameObject works like a set of GameObjects, identified by their name, so there can be only one of each in it.
So to elaborate lets say we have
class SimpleNavigation : GameComponent {...}
class AdvancedNavigation : GameComponent {...}
class SensorSystem : GameComponent {...}
Then i would give SimpleNavigation and AdvancedNavigation the Name "navigation" and to the SensorSystem the name "sensor"
So i cannot have both SimpleNavigation and AdvancedNavigation in the above example.
Hope that makes sense.
Thanks in advance.
p.s. I fear that i might be placing too many constrains when there isn't much to gain and longterm the specifications might change, but that is outside of the scope of the question i guess
Firstly, if all NavigationComponents will have the same name, how will you distinguish between them? If you only want to return a single NavigationComponent, you will need a unique identifier.
You can use the OfType() method to return all instances of a type:
var navigationComponents = _components.OfType<NavigationComponent>();
From there, you can select a single NavigationComponent by some unique identifier:
NavigationComponent nc = navigationComponents.Where(n => n.Id == 1);
Rewritten:
You've mentioned that .Name should remain as a property on your GameComponent class--so one option to consider is overriding the equality operator to say "if two instances of GameComponent have the same name then they should be considered equal". Combined with Dave's suggestion of using OfType() you would have something like this:
class GameObject
{
private List<GameComponent> _components = new List<GameComponent>();
public T GetComponent<T>(string name) where T : GameComponent, new
{
return
(from c in _components.OfType<T>()
where c == new T { Name = name }
select c).FirstOrDefault();
}
}
class GameComponent
{
public string Name { get; set; }
public bool Equals(GameComponent other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return Equals(other.Name, Name);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj.GetType() != typeof(GameComponent))
{
return false;
}
return Equals((GameComponent)obj);
}
public override int GetHashCode()
{
return (Name != null ? Name.GetHashCode() : 0);
}
}
It's worth thinking through whether or not you want to implement this approach--it will affect any equality-checks (not reference-checks). However it's a very powerful ability to say "X and Y should be considered equal when X"--and equality overloading lets you implement that logic in a single centralized home (right on the entity).
Update: In response to your edit:
Then i would give SimpleNavigation and
AdvancedNavigation the Name
"navigation" and to the SensorSystem
the name "sensor"
If this is the case, then you really can't hope to have an interface like this...
public T GetComponent<T>() where T : GameComponent { }
...because multiple GameComponent object types may potentially share the same name. So you cannot infer name from type.
Why not go with an enum instead? Then you might have something like this:
public enum ComponentType
{
Navigation,
Sensor // etc.
}
And your GameObject class could in turn hold a Dictionary<ComponentType, GameComponent>.
Then your GetComponent method could look like this:
GameComponent GetComponent(ComponentType type) { }
Anyway, it's a thought...
I think what makes more sense is this:
Firstly, if you're looking up by name, use a Dictionary<string, GameComponent> instead of a List<GameComponent>. This will give you O(1) lookup time instead of O(N).
Now, if you want name to be dependent on type, define your GameComponent class like this:
class GameComponent
{
public virtual string Name
{
// You could also hard-code this or cache it
// for better performance.
get { return this.GetType().Name; }
}
}
You might then choose to override the Name property in your derived methods, like so:
class NavigationComponent : GameComponent
{
public override string Name
{
// This returns the same thing as GetType().Name,
// but it's faster.
get { return "NavigationComponent"; }
}
}
Then your AddComponent method would be:
public void AddComponent(GameComponent component)
{
_components.Add(component.Name, component);
}
and your GetComponent method would be simple:
public T GetComponent<T>() where T : GameComponent
{
return _components[typeof(T).Name] as T;
}
Related
It's better to start with code
public interface ICondition<TObject> where TObject : notnull
{
public TObject? Value { get; } //Condition value for primitives
public bool InverseResult { get; init; }
public bool IsSatisfiedBy(TObject obj)
{
return InverseResult ? !Check(obj) : Check(obj);
}
public bool Check(TObject obj);
}
This interface is implemented much in classes like IntegerCondition, BooleanCondition. And other primitives. For example GreaterIntegerCondition, ExactlyIntegerCondition
public interface ITemplate<TObject> : ICondition<TObject> where TObject : notnull
{
TObject? ICondition<TObject>.Value => default;
public IEnumerable<IMappedCondition<TObject>> ConditionsMap { get; }
bool ICondition<TObject>.InverseResult
{
get => false;
init { }
}
public string TemplateName { get; set; }
bool ICondition<TObject>.Check(TObject obj)
{
return ConditionsMap.All(c => c.CheckCondition(obj)) && ConditionsMap.Any();
}
}
This interface extends previous. It can contain many of conditions that mapped to TObject's properties. It is used on more complex objects that can have many properties.
At the end I have this class (simplified version below)
public class FooBunchTemplate
{
public List<ICondition<Foo>> Conditions { get; }
public bool CheckBunch(HashSet<Foo> bunch)
{
var remainingConditions = Conditions.ToList();
foreach(Foo foo in bunch)
{
var matched = remainingConditions.FirstOrDefault(c => c.IsSatisfiedBy(foo));
if(matched == null) return false;
remainingConditions.Remove(matched);
}
return true;
}
}
So, we have set of Foo. Every Foo in HashSet is unique. But problem is the one Foo must match only one condition "slot". There are templates that can be satisfied by different objects (even hundreads of them)
If I just exclude matches, then there might be a situation where the more general condition will be excluded by Foo which would fit also the narrower pattern. Then the CheckBunch() will return false, although if the conditions are set correctly, it should have returned true.
You can think of it as a slot machine. The order is unimportant, but the link 1 condition - 1 object is important.
Example template:
A or B
A
C
Bunch:
CAB
We search C template and exclue 3rd
We search A template and exclude 1st
We search B template but 1st was excluded before.
False is returned
//Wrong result. CAB matches this template, because we can put A in second slot and B in first.
Which approach will be fast and reliable in that situation. Number of conditions in BunchTemplate always fit count of Foo in bunch
I'm trying to find a way to refine some code that I have. I work with a 3rd party API that has a REALLY complicated API request object (I'll call it ScrewyAPIObject) that has tons of repetition in it. Every time you want to set a particular property, it can take a page worth of code. So I built a library to provide a simplified wrapper around the setting/getting of its properties (and to handle some value preprocessing).
Here's a stripped-down view of how it works:
public abstract class LessScrewyWrapper
{
protected ScrewyAPIRequest _screwy = new ScrewyAPIRequest();
public void Set(string value)
{
Set(_getPropertyName(), value);
}
public void Set(string property, string value)
{
// Preprocess value and set the appropriate property on _screwy. This part
// has tons of code, but we'll just say it looks like this:
_screwy.Fields[property] = "[" + value + "]";
}
protected string _getPropertyName()
{
// This method looks at the Environment.StackTrace, finds the correct set_ or
// get_ method call and extracts the property name and returns it.
}
public string Get()
{
// Get the property name being access
string property = _getPropertyName();
// Search _screwy's structure for the value and return it. Again, tons of code,
// so let's just say it looks like this:
return _screwy.Fields[property];
}
public ScrewyAPIRequest GetRequest()
{
return _screwy;
}
}
Then I have a child class that represents one specific type of the screwy API request (there are multiple kinds that all have the same structure but different setups). Let's just say this one has two string properties, PropertyA and PropertyB:
public class SpecificScrewyAPIRequest : LessScrewyWrapper
{
public string PropertyA
{
get { return Get(); }
set { Set(value); }
}
public string PropertyB
{
get { return Get(); }
set { Set(value); }
}
}
Now when I want to go use this library, I can just do:
SpecificScrewyAPIRequest foo = new SpecificScrewyAPIRequest();
foo.PropertyA = "Hello";
foo.PropertyB = "World";
ScrewyAPIRequest request = foo.GetRequest();
This works fine and dandy, but there are different kinds of data types, which involves using generics in my Set/Get methods, and it just makes the child classes look a little kludgy when you're dealing with 50 properties and 50 copies of Get() and Set() calls.
What I'd LIKE to do is simply define fields, like this:
public class SpecificScrewyAPIRequest : LessScrewyWrapper
{
public string PropertyA;
public string PropertyB;
}
It would make the classes look a LOT cleaner. The problem is that I don't know of a way to have .NET make a callback to my custom handlers whenever the values of the fields are accessed and modified.
I've seen someone do something like this in PHP using the __set and __get magic methods (albeit in a way they were not intended to be used), but I haven't found anything similar in C#. Any ideas?
EDIT: I've considered using an indexed approach to my class with an object-type value that is cast to its appropriate type afterwards, but I'd prefer to retain the approach where the property is defined with a specific type.
Maybe in your case DynamicObject is a suitable choice:
public class ScrewyDynamicWrapper : DynamicObject
{
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
// get your actual value based on the property name
Console.WriteLine("Get Property: {0}", binder.Name);
result = null;
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
// set your actual value based on the property name
Console.WriteLine("Set Property: {0} # Value: {2}", binder.Name, value);
return true;
}
}
And define your wrapper objects:
public class ScrewyWrapper
{
protected dynamic ActualWrapper = new ScrewyDynamicWrapper();
public int? PropertyA
{
get { return ActualWrapper.PropertyA; }
set { ActualWrapper.PropertyA = value; }
}
public string PropertyB
{
get { return ActualWrapper.PropertyB; }
set { ActualWrapper.PropertyB = value; }
}
}
However, you can't rely on the property type inside ScrewyDynamicWrapper with this approach, so it depends on your actual API requirements - maybe it won't work for you.
Instead of fields, If you define as property in class, It will be more easy.
public class SpecificScrewyAPIRequest
{
public string PropertyA { get; set; }
public string PropertyB { get; set; }
}
Then you can create extension generic method to return ScrewyAPIRequest object.
public static class Extensions
{
public static ScrewyAPIRequest GetRequest<T>(this T obj)
{
ScrewyAPIRequest _screwy = new ScrewyAPIRequest();
var test= obj.GetType().GetProperties();
foreach (var prop in obj.GetType().GetProperties())
{
_screwy.Fields[prop.Name] = prop.GetValue(obj, null);
}
return _screwy;
}
}
Now you can easily get ScrewyAPIRequest from any class object.
Your code will look like following.
SpecificScrewyAPIRequest foo = new SpecificScrewyAPIRequest();
foo.PropertyA = "Hello";
foo.PropertyB = "World";
ScrewyAPIRequest request = foo.GetRequest();
I am currently trying to test that two C# objects are the same (not referencing the same object, but have the same values). Trying to use Assert.Equals gives me "Assert.Equals should not be used for Assertions". What should I use ?
Use Asset.AreEqual.
The Asset class is a child of the object class (like any class in C#) and when you call Asset.Equals you are actually calling the method object.Equals which is not what you want to do.
Programmers of NUnit probably put an exception in Asset.Equals to prevent people from making the mistake of using the wrong equality method.
for this, you should override Equals Method in Your Class
public class Student
{
public int Age { get; set; }
public double Grade { get; set; }
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (!(obj is Student))
{
return false;
}
Student st = obj as Student;
return (st.Age == this.Age &&
st.Grade == this.Grade);
}
}
then you can write this Code in Your Test Class:
Assert.AreEqual(st1,st2);
I have HashSet of my custom class:
public class Vertex
{
public string Name;
public override bool Equals(object obj)
{
var vert = obj as Vertex;
if (vert !=null)
{
return Name.Equals(vert.Name, StringComparison.InvariantCulture);
}
return false;
}
}
And now I have tow hashsets
HashSet<Vertex> hashSet1 = new HashSet<Vertex>();
HashSet<Vertex> hashSet1 = new HashSet<Vertex>();
And now I'd like to have in hashSet1 only Vertexes that are not in hashSet2
So I use ExceptWith method
hashSet1.ExceptWith(hashSet2);
But this doesn't work.
I suppose that this doesn't work because I have complex type.
So the question is: is there some interface required to be implemented in Vertex class to make this thing work?
I know that while creation of HashSet I can pass a EqualityComparer but it seems to me that it would be more elegant to implement some comparing interface method in Vertex class.
Is it possible or I just doesn't understand sth?
Thanks.
When overriding Equals you should also override GetHashCode. HashSet (and other hashing structures like Dictionary) will first calculate a hash code for your objects to locate them in tne structure before comparing elements with Equals.
public override int GetHashCode()
{
return StringComparer.InvariantCulture.GetHashCode(this.Name);
}
You don't have to implement any interface (although IEquatable<T>) is encouraged. When you create a hash-set without specifying an equality-comparer, it defaults to using EqualityComparer<T>.Default, which asks the objects themselves to compare themselves to each other (special-casing null references).
However, in your case, your equality contract is broken since you haven't overriden GetHashCode. Here's how I would fix your type:
public class Vertex : IEquatable<Vertex>
{
public string Name { get; private set; }
public Vertex(string name)
{
Name = name;
}
public override int GetHashCode()
{
return StringComparer.InvariantCulture.GetHashCode(Name);
}
public override bool Equals(object obj)
{
return Equals(obj as Vertex);
}
public bool Equals(Vertex obj)
{
return obj != null && StringComparer.InvariantCulture.Equals(Name, obj.Name);
}
}
Would you mind overriding the .GetHashCode()too?
Here's the reference.
You have to override GetHashCode with Equals overriding.
Object.Equals Method:
Types that override Equals(Object) must also override GetHashCode; otherwise, hash tables might not work correctly.
In NHibernate 3.0 Cookbook, there is a sample implementation for a base Entity type. The equals is implemented like this:
public abstract class Entity<TId>
{
public virtual TId Id { get; protected set; }
public override bool Equals(object obj)
{
return Equals(obj as Entity<TId>);
}
private static bool IsTransient(Entity<TId> obj)
{
return obj != null && Equals(obj.Id, default(TId));
}
private Type GetUnproxiedType()
{
return GetType();
}
public virtual bool Equals(Entity<TId> other)
{
if (other == null) return false;
if (ReferenceEquals(this, other)) return true;
if (!IsTransient(this) && !IsTransient(this) && Equals(Id, other.Id))
{
var otherType = other.GetUnproxiedType();
var thisType = GetUnproxiedType();
return thisType.IsAssignableFrom(otherType) ||
otherType.IsAssignableFrom(thisType);
}
return false;
}
}
The reason for the GetUnproxiedType() method is this: There is an abstract base class Product, a concrete class Book which inherits from Product and a dynamic proxy class ProductProxy used by NHibernate for lazy loading. If a ProductProxy representing a Book and a concrete Book have the same Ids, they should be treated as equal. However I don't really see why calling GetType() on a ProductProxy instance should return Product in this case, and how it helps. Any ideas?
I actually went ahead and wrote to the author of the book about this code. It turns out this is due to how the proxy wrapping works. Here is his response:
"If you don't understand how the proxy frameworks work, the idea can seem magical.
When NHibernate returns a proxy for the purposes of lazy loading, it returns a proxy instance inherited from the actual type. There are a few members we can access without forcing a load from the database. Among these are proxy's Id property or field, GetType(), and in some circumstances Equals() and GetHashCode(). Accessing any other member will force a load from the database.
When that happens, the proxy creates an internal instance. So, for example, a lazy loaded instance of Customer (CustomerProxy102987098721340978), when loaded, will internally create a new Customer instance with all of the data from the database. The proxy then does something like this:
public overrides string Name
{
get {
return _loadedInstance.Name;
}
set { _loadedInstance.Name = value; }
}
Incidentally, it's this overriding that requires everything to be virtual on entities that allow lazy loaded.
So, all calls to the Name property on the proxy are relayed to the internal Customer instance that has the actual data.
GetUnproxiedType() takes advantage of this. A simple call to GetType() on the proxy will return typeof(CustomerProxy02139487509812340). A call to GetUnproxiedType() will be relayed to the internal customer instance, and the internal customer instance will return typeof(Customer)."
With current (v5.x) NHibernate proxy factories (static or dynamic, static being available since v5.1), this pattern is actually broken. The v5 built-in proxy factories do not intercept private methods.
And I think that was already the case for v4 ones.
For this pattern to work with current built-in proxy factories, GetUnproxiedType should be virtual (so not private by the way, but protected).
Otherwise, use NHibernateUtil.GetClass, which is meant for this and does not rely on brittle tricks. Its documentation warns it will initialize the proxy by side effect, but anyway the GetUnproxiedType trick must do the same for working.
Of course using NHibernateUtil.GetClass means having a direct dependency to NHibernate in a domain model base class. But depending on an implementation trick specific to an external (from the domain viewpoint) library implementation is no better in my opinion.
Moreover, some changes may cause the GetUnproxiedType trick to be even more broken in the future, like some ideas for reducing the number of cases causing a proxy to get initialized when it could be avoided. (See here by example.)
If you really want a GetUnproxiedType method not depending on a direct NHibernate reference, I think the only theoretically "safe" solution is to have it abstract and overridden in each concrete entity class for yielding typeof(YourEntityClass). But in practice, it would be cumbersome and error-prone (bad copy-paste for creating a new entity, forgetting to change that method...), while the abstract part won't help in case some concrete entity classes are further specialized through inheritance.
Another trick could be, from the type obtained by GetType, to check to which assembly it belongs (the proxy type will not belong to one of your assemblies), for searching the first type in the hierarchy belonging to your domain model assembly(ies).
Note that if the proxy is a proxy of a base class, not of a concrete class, and your helper method is set as private, it will yield the base class type, without initializing the proxy. Performance-wise, this is better. While a virtual GetUnproxiedType simply returning GetType would return the concrete class type with current proxy factories, but it would also initialize the proxy.
We use NH 2 and this example did not work for us. (It FAILED to unproxy the type and left proxy type, see below).
It said that 2 entities with the same id are not equal, when one of them is proxy(of COrganization) and other is not(DOrganization).
When we had a hierarchy:
class Organization
class AOrganization : Organization
class COrganization : Organization
{
public virtual COrganization GetConcrete()
{
return null;
}
}
class DOrganization : COrganization
{
public virtual COrganization GetConcrete()
{
return this;
}
}
AOrganization aOrganization;
COrganization cOrganization;
contract = new CContract(aOrganization, cOrganization as COrganization); //(COrganization)(cOrganization.GetConcrete()),
So CContract has a field of type COrganization. With a setter
public class Contract: Entity <short>
{
public virtual COrganization COrganization
{
get { return cOrganization; }
protected internal set
{
if (cOrganization != null && value != cOrganization) // != calls ==, which calls Equals, which calls GetUnproxiedType()
throw new Exception("Changing organization is not allowed.");
}
cOrganization = value;
}
}
private COrganization cOrganization;
}
We constructed new Contract, its constructor set the COrganization field pointing to some organization. Then we called UnitOfWork.Commit, NH tried to set COrganization field again (with the same id), GetUnproxiedType worked incorrectly, new and old values were recognized as non-equal, and exception was thrown...
Here is the place where error showed up:
var otherType = other.GetUnproxiedType();
var thisType = GetUnproxiedType();
return thisType.IsAssignableFrom(otherType) ||
otherType.IsAssignableFrom(thisType);
In debugger: otherType == COrganizationProxy - GetUnproxiedType failed...
thisType == DOrganization
COrganizationProxy and DOrganization both inherit COrganization.
So they are not IsAssignableFrom for each other...
Why does this example work for you?
Maybe because we have NH 2.0 or 2.1?
Or because of simple "cOrganization as COrganization" instead of "(COrganization)(cOrganization.GetConcrete())"?
Or because we have implementation of ==, != and Equals not only in Entity, but in Organization too?
public abstract class Organization : Entity<int>
{
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public static bool operator ==(Organization object1, Organization object2)
{
return AreEqual(object1, object2);
}
public static bool operator !=(Organization object1, Organization object2)
{
return AreNotEqual(object1, object2);
}
}
public abstract class Entity<TId>
{
public virtual TId Id { get; /*protected*/ set; }
public override bool Equals(object obj)
{
return Equals(obj as Entity<TId>);
}
private static bool IsTransient(Entity<TId> obj)
{
return obj != null &&
Equals(obj.Id, default(TId));
}
private Type GetUnproxiedType()
{
return GetType();
}
public virtual bool Equals(Entity<TId> other)
{
if (other == null)
return false;
if (ReferenceEquals(this, other))
return true;
if (!IsTransient(this) &&
!IsTransient(other) &&
Equals(Id, other.Id))
{
var otherType = other.GetUnproxiedType();
var thisType = GetUnproxiedType();
return thisType.IsAssignableFrom(otherType) ||
otherType.IsAssignableFrom(thisType);
}
return false;
}
public override int GetHashCode()
{
if (Equals(Id, default(TId)))
return base.GetHashCode();
return Id.GetHashCode();
}
/// This method added by me
/// For == overloading
protected static bool AreEqual<TEntity>(TEntity entity1, TEntity entity2)
{
if ((object)entity1 == null)
{
return ((object)entity2 == null);
}
else
{
return entity1.Equals(entity2);
}
}
/// This method added by me
/// For != overloading
protected static bool AreNotEqual<TEntity>(TEntity entity1, TEntity entity2)
{
return !AreEqual(entity1, entity2);
}
}