So, I'm currently working on a strategy game that involves 3 types of buildings: "Production", "Storage", and "Refining".
Any building can belong to one or more of these types, so a Storage building could also be a Refining building and should then inherit the functionality of both of these types.
Example:
public class Stronghold : Building, IStorage, IRefining, IProduction
{
public RefiningOption[] RefiningOptions { get; set; }
}
public interface IRefining
{
public RefiningOption[] RefiningOptions { get; set; }
}
I went about implementing this using interfaces, but I am running into the issue that Unity does not allow you to serialize properties and interfaces can not contain fields.
Is there a way around this that would allow me to inherit from multiple different types in a neat way, or am I approaching this all wrong? I can think of a solution that would involve using separate components for the functionality of each building type, but before I implement that, I wanted to know what the "correct" solution would be.
Thanks in advance. I'm trying to expand my toolset, so any feedback is welcome.
Just like the answer above but in a more "compact" way
[field: SerializeField] public RefiningOption[] RefiningOptions { get; set; }
This is an auto-property that generates a backing field that you can access directly by typing [field: "Your_Attribute_Here"], this is the same as having a [Serialized] private field with a public property exposing it.
just like this ? create a field in private. and this private field can be serialize
private RefiningOption[] _refiningOptions;
public RefiningOption[] RefiningOptions
{
get { return _refiningOptions; }
set { _refiningOptions = value; }
}
Related
I have a set of interfaces using each others like this:
public interface IModel
{
string Name { get; }
IModelParameters Parameters { get; }
}
public interface IModelParameter
{
int Value { get; }
}
public interface IModelParameters: IList<IModelParameter>
{
void DoSomething();
}
And to implement those interfaces, I have defined those classes:
public class Model: IModel
{
string Name { get; internal set; }
public ModelParameters Parameters { get; private set; }
IModelParameters IModel.Parameters { get { return Factors; } }
}
public class ModelParameter: IModelParameter
{
int Value { get; internal set; }
}
public class ModelParameters: List<ModelParameter>, IModelParameters
{
void DoSomething()
{
// actual code
}
}
This does not compile because List<ModelParameter> implements IList<ModelParameter> and not IList<IModelParameter> as required by IModelParameters
Changing ModelParameters to be List<IModelParameter> fixes the compilation but it breaks Entity Framework migration generation because it no longer recognizes the list as a navigation property because the type parameter is an interface, not a regular class.
I could also have ModelParameters not implement IModelParameters and declare a second class that gets instantiated and filled directly in the IModelParameters.Factors getter inside Model
But this feels inefficient as it effectively creates two instances of the same list, one for Entity framework and a temporary one for use by the rest of the application. And because this temporary is filled at runtime, it introduces another potential point of failure.
This is why I'm trying to find a way to express the fact List<ModelParameter> implements IList<IModelParameter> just fine because ModelParameter implements IModelParameter itself.
I have a feeling that covariance/contravariance might be of help here, but I'm not sure how to use that.
You cannot do this. It it was possible to cast a List<ModelParameter> to IList<IModelParameter> you could try adding a object of another type to the list, i.e. class MyOtherModelParam : IModelParameter. And that is a contradiction since the type system guarantees that the list only contains ModelParameter objects.
You could replace it with IReadOnlyList<T>, since this interface do not expose any add or set methods it is safe to cast a List<ModelParameter> to IReadOnlyList<IModelParameter>.
Another possible solution would be to just remove the interface. If you intend to have only one implementation of IModelParameter, the interface serves little purpose, and you might as well just remove it.
I need a way of distinguishing class objects which a user is passing into my custom control. The reason for this, is so I can handle certain logic on the back end, completely extracted and uncontrollable by the user. The user would pass in object collections like this...
<Grid>
<nexus:NexusEditor
SourceTeams="{Binding Teams}"
SourcePlayers="{Binding Players}"
SourceLocations="{Binding Locations}"/>
</Grid>
If i were to forloop through all these objects in my custom control, I need a way of marking the incoming objects so i know which Source there were passed through.
This can't be easily done at runtime and is arguably the wrong design in C#. There are other ways to solve this. You can, for example, create a wrapper around the Connection class and inject an instance of Connection into it. ConnectionWrapper can then inherit AbstractBase
public class ConnectionWrapper: AbstractBase
{
public ConnectionWrapper(Connection connnection)
{
}
private override int _type {get; set;}
}
It's really hard to give something concrete without knowing more about your requirements, but I think something like this might do what you want:
public interface ITyped
{
int Type { get; }
}
public class Connection : ITyped
{
public string Name { get; set; } // NOTE: public setters are Bad Code(tm) for anything but the dumbest DTO objects
public int Type { get { return 1; } } // specify type for connections here
}
Usage:
foreach (var typed in connections.Concat<ITyped>(groups))
{
DoStuffWith(typed);
}
A simple example.
alt text http://img19.imageshack.us/img19/1854/51445300.jpg
A have a class TDMReader which is a buldier of TDMFile objects and I am using Auto Implemented Properties f.e.
public string Name
{
get;
set;
}
public Group[] Groups
{
get;
set;
}
What I want to do is to make setter accessible only for TDMReader methods.
In C++ i could have friends methods to access private variables, in Java I could make them in one packet and so access to fields. I have some ideas but with this auto-implemetation is a bit more complicated to do.
Any ideas with a nite solution?:)
Automatic properties have no bearing on this - the same options are available for automatic properties and "manual" properties. You can restrict the access of the setter like this:
// Setter access only to this type and nested types
public string Name { get; private set; }
// Setter access within the assembly
public Group[] Groups { get; internal set; }
etc
... but you can't do it for a single class (unless that class is nested within the declaring type, in which case private would be fine). There's no namespace-restricted access in .NET or C#.
(It's not entirely clear which class the properties are declared in - if they're TdmReader properties, then just make them private. If they're TdmFile properties, you have the problem described above.)
Like this:
public string Name
{
get;
private set;
}
public Group[] Groups
{
get;
private set;
}
By adding the private keyword, the setters will only be accessible by code in the same class. You can also add internal to make it accessible to code in the same project.
Note that exposing an array as a property is extremely poor design.
Instead, you should expose a Collection<Group> or ReadOnlyCollection<Group>, in the System.Collections.ObjectModel namespace.
excuse what seems like a real noobie question but how can I implement the following
public interface IViewModel {
void Map<T>();
}
public class CarViewModel : IViewModel
{
public string Color { get; private set; }
public int Tyres { get; private set; }
public CarViewModel(Car _car)
}
//this is where the problem is - there can be many differnt kind of object but I want them all to implement a Map function. I want to be able to assign the properties to incoming object. I also need to cater for IList of cars coming in that need to be populated. I suspect I am not using Generics properly
public void Map<T>(Car _car){
Color = _car.Color;
Tyres = _car.Tyres;
}
Do you mean this?
public interface IViewModel<T>
{
void Map(T domainObject);
}
public class CarViewModel : IViewModel<Car>
{
public Map(Car domainObject) { ... }
}
You say:
I suspect I am not using Generics properly
and you are correct. Additionally, you are not using polymorphism properly.
If you want to polymorphically accept several different types that all have something in common, then you need to create an interface that is the parent type of all of the types you will be using. You can do this without using any Generics at all.
What Generics (aka parametric polymorphism) gives you is a way to create one type that is parameterized by another type (and thus behaves like many different types). For example, IList<T> is parameterized by a type variable T -- then IList<string> and IList<int> are two separate types (with many possible subtypes each), but you only have to write the code once.
What are your actual requirements for this design? What are your ViewModel classes trying to accomplish?
I have a base type which stores information about a question in a question pool for a system which generates practice question sets to help people study for multiple choice tests. The only information that is stored in it are the answers, the prompt and question number. When I create a practice test, I need to augment the type with some properties to store the answer submitted (the test can be taken in parts), and so I created the following classes:
public class MultipleChoiceQuestion
{
public Int32 Number { get; internal set; }
public String Prompt { get; internal set; }
public MultipleChoiceAnswer[] Choices { get; internal set; }
// constructors, etc...
}
public class PracticeTestQuestion : MultipleChoiceQuestion
{
public MultipleChoiceAnswer AnswerSelected { get; set; }
// is this right?
public PracticeTestQuestion(MultipleChoiceQuestion question)
{
...
}
}
Originally I had the MultipleChoiceQuestion as just a member of PracticeTestQuestion, but it added a lot of extra dots in my property accessors, and so I changed it to inherit the class as listed above. Currently I am assigning all of the properties line for line in the constructor, and but it feels sort of cumbersome, and I was wondering if there is a better way.
The C# compiler doesn't like upsizing types for good reasons, so my question is what is the best way to go about instantiating my PracticeTestQuestions from their MultipleChoiceQuestion base types?
I would add a constructor to MultipleChoiceQuestion that takes another MultipleChoiceQuestion. If necessary it can assign each of the properties in the constructor, but that's more appropriate, since it has the knowledge of its own properties.
Then in PracticeTestQuestion, you can just do:
public PracticeTestQuestion(MultipleChoiceQuestion question) : base(question) { }
and be done with it.
My first gut reaction is to use a factory to create questions. You ask the factory for a MCQ or a PTQ and it creates the right one.
This is also more extensible to essay questions, true false, etc.