Can I avoid Exporting LayerClass in Views derived from iPhoneOSGameView? - c#

Given a class:
public class BaseGameView : OpenTK.Platform.iPhoneOS.iPhoneOSGameView {
Constructing BaseGameView at runtime will throw System.Exception: Failed to find selector layerClass... This is easily resolved by adding the following to the class definition:
[Export ("layerClass")]
public static new Class GetLayerClass()
{
return iPhoneOSGameView.GetLayerClass();
}
This is not so undesirable until I derive another class as follows:
public class DerivedGameView : BaseGameView {
Constructing the DerivedGameView also throws the same exception unless I Export("layerClass") from that class as well.
How can I DRY this out? I have a handful of these derived views and they all have to have the same snippet of code exporting the layer class... I'd rather not repeat it.
A related question is:
Why is this not necessary for a class simply derived from UIView?
Cheers!

This is currently a limitation inside MonoTouch - static methods from base classes aren't exported.
I have filed a bug report for this: https://bugzilla.xamarin.com/show_bug.cgi?id=6170 - you can CC yourself on this bug to get notified when it's fixed.

Related

PostSharp aspect build error on class derived from generic type

I am trying to use the Dispatched aspect on a class to push execution to the UI thread but I am getting an error at build time. Here is the error:
You cannot add an aspect to a generic type instance. Add the aspect to the corresponding generic type definition.
It seems to have a problem with me putting the aspect on a class that derives from a generic type.
Here is a simplified code sample that can reproduce this:
interface IView
{
}
class Presenter<T>
{
}
class DataPresenter : Presenter<IView>
{
[Dispatched]
void DoSomething()
{
}
}
Am I missing something or is it not possible to use aspects on a class that inherits from generic types?
As Daniel mentions in the comments, this is a bug in PostSharp but I found a work around. I modified the presenter class:
class Presenter<T> : DispatcherObject, IDispatcherObject
{
IDispatcher IDispatcherObject.Dispatcher => DispatcherFactory.GetDispatcherForWindowsDispatcher(Dispatcher);
}
In my code Presenter was already inheriting from DispatcherObject, so implementing the IDispatcherObject interface fixed my issue.

Ambiguous step definitions when try to implement in generic fashion c#, specflow

I have implemented code in following fashion.
public abstract class BaseDocumentStep<T> where T : class, new()
{
protected T _document;
[Given(#"I Add New '(.*)'")]
public void GivenIAddNew(string p0)
{
Console.WriteLine(p0);
}
}
[Binding]
public class CustomerSteps : BaseDocumentStep<Customer>
{
}
[Binding]
public class EmployeeSteps : BaseDocumentStep<Employee>
{
}
Feature Files :-
a) Customer Feature
Scenario: Add New Customer
Given I Add New 'Customer'
b) Employee Feature
Scenario: Add New Employee
Given I Add New 'Employee'
When I run these scenarios. I got following error :
-> binding error: Ambiguous step definitions found for step 'Given I Add New 'Customer'': BaseDocumentStep1.GivenIAddNew(String), BaseDocumentStep1.GivenIAddNew(String)
After Scenario
I am not able to figure out, why specflow consider this step as ambiguous ?
Thanks in Advance.
Adi.
Adi,
Are there any reasons you want to use the abstract class for your tests? I have been using specflow for a few years now, and I have always tried to keep them simple and linear. Can you try to replace your step definition file with this:
[Binding]
public class EmployeeSteps
{
[Given(#"I Add New '(.*)'")]
public void GivenIAddNew(string p0)
{
Console.WriteLine(p0);
}
}
this is working fine for me. This should work out fine unless you have other reasons not to keep your steps this simple.
The problem here is that in Specflow all steps are global, and so if you declare a step in a base class, that step is also declared in every derived class. So you get one instance of
[Given(#"I Add New '(.*)'")]
public void GivenIAddNew(string p0)
{
Console.WriteLine(p0);
}
in CustomerSteps and EmployeeSteps
Step binding methods should not be declared in base classes, the steps will always be able to be found due to the fact that they are global.
It's not exactly clear what you want to achieve with your generic design, but perhaps if you give a bit more information about that (probably another question is better) then we might be able to help you get to a solution that does not require inheritance with binding classes.

Registering instances of unknown lifetime

Let's assume we have 3 different assemblies
Common assembly
public abstract class ContextBase
{
}
public abstract class ContextManager<T> where T: ContextBase
{
// contains all the context managing logic.
public T FindContext()
{
// ...
}
}
Application specific assembly 2:
public class SpecialContext : ContextBase
{
// custom properties specific to this type of context
}
public class SpecialContextManager : ContextManager<SpecialContext>
{
// inherits most of the logic from its base class but has some
// overrides to achieve a slightly different behavior
}
Application specific assembly 3:
public class OtherContext : ContextBase
{
// custom properties specific to this type of context
}
public class OtherContextManager : ContextManager<OtherContext>
{
// inherits most of the logic from its base class but has some
// overrides to achieve a slightly different behavior
}
The motivation for the abstract generic ContextManager class is, that each ContextManager keeps a static collection of objects specific for the given type T. Of course you could have done something like that Dictionary>.. but I liked the generic base class approach more.
Question
Now I want to make a GUI to show/find all contexts. This means all kinds of contexts.
I don't want to write a GUI for each application in each application assembly.
I was thinking of a "common GUI" which shows me all currently active Contexts no matter what type they are (It would be cool to know the type though to show some more detailed information in the GUI). I can obviously find all the contexts using the respective ContextManager instances - but how to I get a grip on them?
This is what I thought of (and rejected in terms of bad design):
public static class CmInstanceMonitor
{
private static List<ContextManager<ContextBase>> _contextMgrs = new List<ContextManager<ContextBase>>;
public static void RegisterInstance(ContextManager<ContextBase> cm)
{
// probably I should make sure I don't add the same object twice
// unfortunately I cannot use the Type yet as this method is invoked
// by the base class ctor() :(
_contextMgrs .Add(cm);
}
}
This way my ContextManager probably lives forever because of the static object that holds a reference to it. Not what I intended. And putting some code into the ContextManager finalizer probably won't do any good because the object will not be GC'ed anyway because of the static reference.
I'm stuck! :)
You can use Weak References. This allows you to maintain a list of all managers without having an impact on Garbage Collection.
However, using generics has some drawbacks in this case. The class SpecialContextManager can be cast to ContextManager<SpecialContext>. That's fine. However, this class cannot be converted to ContextManager<ContextBase>, because those are two different classes. Therefore, you cannot call
RegisterInstance(ContextManager<ContextBase>) passing a concrete manager. So you could either store objects (or WeakReferences to objects) in your list or go with a different approach (e.g. getting all classes via reflection). But then again, the return type of a method that retrieves all managers must be object in some way.

Passing a derived class to a web service method that takes an abstract type

I have a bizarre problem that is doing my head in.
I have the following classes defined in a single project:
public abstract class AbstractUnitModel {
public void executeRemoteModel(){}
}
//this class also implements a seperate interface, but I dont think that is the issue
public class BlastFurnaceUnitModel : AbstractUnitModel, IUnitModel {}
Now if I try something like this, it works as expected:
class Class1
{
public void method1() {
BlastFurnaceUnitModel b = new BlastFurnaceUnitModel();
method2(b);
}
public void method2(AbstractUnitModel a) {}
}
Now I have another project that exposes a web method. This method takes an AbstractUnitModel and executes it remotely, then sends the results back to the client. So on the server I have this:
[WebMethod]
public AbstractUnitModel remotelyExecuteUnitModel(UnitModelWrapperInterface.AbstractUnitModel unitModel)
{
unitModel.executeRemoteModel();
return unitModel;
}
And on the client I have this:
public void remoteExecution() {
var unitModelWebService = new UnitModelRemoteServer.RemoteModelExecutionWebService();
unitModelWebService.remotelyExecuteUnitModelCompleted += new UnitModelRemoteServer.remotelyExecuteUnitModelCompletedEventHandler(remoteExecutionCompleted);
unitModelWebService.remotelyExecuteUnitModelAsync(this.remoteBF);
}
But my project will not compile, and I get these errors:
Error 109 The best overloaded method match for 'CalibrationClient.UnitModelRemoteServer.RemoteModelExecutionWebService.remotelyExecuteUnitModelAsync(CalibrationClient.UnitModelRemoteServer.AbstractUnitModel)' has some invalid arguments
Error 110 Argument '1': cannot convert from 'UnitModelWrapperInterface.BlastFurnaceUnitModel' to 'CalibrationClient.UnitModelRemoteServer.AbstractUnitModel'
I can not figure out why this is happening. I have references in the server project to the namespace where AbstractUnitModel is defined. The only thing that looked a little funny to me is that it is using AbstractUnitModel from the 'CalibrationClient' namespace rather than the UnitModelWrapperInterface. It seems when VS generates the proxy for a webservice on the client it creates a partial abstract implementation of AbstractUnitModel. Is this the source of my problem? If so, how might I go about fixing it?
edit for solution: As pointed out, the client needs to know about all classes that could be sent across the wire. I ended up solving this by removing the generated proxy classes and referencing the common library. Not ideal but good enough in this situation.
This happens because the WSDL tool creates proxy classes (open the service code file and you'll see them) which are the classes used to instantiate when objects come from the service.
If you want to avoid this, it's best to use WCF. This also deals with the polymorphic returned objects, as webservices also can't deal with polymorphism (so the return type of the remotelyExecuteUnitModel method is always AbstractUnitModel.
You might try [XmlInclude]:
[XmlInclude(typeof(BlastFurnaceUnitModel))]
public abstract class AbstractUnitModel {...}
Worth a try, at least...
(edit) Or at the method level:
[WebMethod(), XmlInclude(typeof(BlastFurnaceUnitModel))]
public AbstractUnitModel remotelyExecuteUnitModel(...) {...}
(less sure about the second)
The class exposed in your WebService is created in a different namespace inside your service reference.
I usually create a method like
WebServiceReferenceNS.AbstractUnitModel ToWebServiceModel(AbstractUnitModel unitModel)
{
}
to prepare the classes for the WebService. But I'd like to see if there's a more elegant solution.

Explicit conversion exists c#

The following line of code presents the title error:
ITestClass t = new TestClass();
TestClass implementation:
public class TestClass : ITestClass {
public static TestClass Instance
{
get
{
return TestClass.Instance;
}
}
//Interface members
}
I have another set of classes with similiar interfaces where this cast works, why doesn't it work here?
Most likely the Interface that you are trying to assign do isn't part of the class that you are newing. Double check your interface implementations for mistakes, this is a completely valid piece of code.
If you have a specific error, provide code that produces the same error, the code you provided does not error when compiled.
I'm not sure about the error you put but the property you listed is a bug. The getter just returns the property and is hence infinitely recursive. This will cause a stack overflow at runtime if you attempt to access it.
The only possibility for such an error is that TestClass or ITestClass doesn't mean the same thing in one case and another.
The most common cause for this is to have the assembly containing TestClass and your main assembly reference 2 different dll files both with an interface named ITestClass.

Categories

Resources