Can somebody familiar with microsoft robotics studio please explain why the handler operations are virtual and some are set as non-virtual ?
[ServiceHandler(ServiceHandlerBehavior.Concurrent)]
public virtual IEnumerator<ITask> GetHandler(Get get)
{
get.ResponsePort.Post(_state);
yield break;
}
vs
[ServiceHandler(ServiceHandlerBehavior.Concurrent)]
public IEnumerator<ITask> SubscribeHandler(Subscribe subscribe)
{
SubscribeRequestType request = subscribe.Body;
LogInfo("Subscribe request from: " + request.Subscriber);
// Use the Subscription Manager to handle the subscribers
yield return Arbiter.Choice(
SubscribeHelper(_submgrPort, request, subscribe.ResponsePort),
delegate(SuccessResult success)
{
// Send a notification on successful subscription so that the
// subscriber can initialize its own state
base.SendNotificationToTarget<Replace>(request.Subscriber, _submgrPort, _state);
},
delegate(Exception e)
{
LogError(null, "Subscribe failed", e);
}
);
yield break;
}
Thanks in advance.
Virtual handlers are used in classes you expect to use as base for other classes. Handlers that are not virtual are either declared as overrides in derived classes, or in classes that will not be derived (as is often the case in sample code).
Refer to the following articles:
http://msdn.microsoft.com/en-us/library/9fkccyh4(v=VS.100).aspx
What are Virtual Methods?
C# virtual methods question
WHy should virtual methods be explicitly overridden in C#?
Related
I want to keep network code separate from my game logic. Not only do I need to do that to be able to share game logic between single and multiplayer game modes, I also want it because of the Separation Of Concerns thing.
My current approach is to generate the code for my network related classes in such a way that there is an online and an offline version. I do this using T4 templates.
The resulting classes look like this:
Standalone/Singleplayer version:
// T4 GENERATED CODE
// Head (Singleplayer version)
class StandaloneHelloWorld : MonoBehaviour, IHelloWorld
{
private string name;
public void SayHello()
{
SayHelloInternal();
}
// Body
public string Name
{
get { return name; }
set { name = value; }
}
void SayHelloInternal()
{
Debug.Log(Name + ": Hello World");
}
}
Multiplayer version:
// T4 GENERATED CODE
// Head (Multiplayer version)
class NetworkedHelloWorld : NetworkBehaviour, IHelloWorld
{
[SyncVar]
private string name;
public void SayHello()
{
CmdSayHello();
}
[Command]
void CmdSayHello()
{
RpcSayHello();
}
[ClientRpc]
void RpcSayHello()
{
SayHelloInternal();
}
// Body
public string Name
{
get { return name; }
set { name = value; }
}
void SayHelloInternal()
{
Debug.Log(Name + ": Hello World");
}
}
They both share an interface to hide the implementation from the callers:
interface IHelloWorld
{
string Name { get; set; }
void SayHello();
}
So as you can see, both implementations use the same body, sharing most of the code, while the entry points depend on the implementation being networked or not. Also note that the two implementations inherit different base classes.
Advantages:
Singleplayer code has no dependencies towards networked code and vice versa
No duplicate code (none that has to be maintained manually at least)
Disadvantages:
Support for interfaces in Unity is limited. I would not be able to reference scene instances of IHelloWorld from inside the Editor.
Having to maintain separate Prefabs for singleplayer/multiplayer game modes
Having to meddle with T4/code generation
Do you know of better ways to deal with this? How did you solve this problem?
You could structure the code in an event-based fashion. This will allow systems to register to events they're interested in. This naturally separates the logic from the network code.
As an example, let's say you want to fire a projectile.
You can fire it by calling:
new Event(EventType.FireProjectile, pos, dir, template)
You can then register systems that are interested in this event:
CollisionSystem.Register(EventType.FireProjectile, (e) => {
CollisionSystem.AddCollider(e.template.bounds);
});
AudioSystem.Register(EventType.FireProjectile, (e) => {
AudioSystem.PlaySound("Woosh");
});
AISystem.Register(EventType.FireProjectile, (e) => {
AISystem.AlertAtPosition(e.pos);
});
What's cool is next you can register this event to the NetworkSystem that will serialize it, move it across the net, deserialize it, and fire it off on the client's machine. So as far as the client is concerned this event was called locally.
NetworkSystem.Register(EventType.FireProjectile, (e) => {
NetworkSystem.Broadcast(e, Channel.Reliable);
});
This is pretty great, except that you'll soon realize that this will cause an infinite loop of events. As you send a FireProjectile event to the other client, they catch it and fire it. Instantly their NetworkSystem catches it and fires it over the net.
To fix this you need two events for every action – a request: FireProjectile, and response: ProjectileFired.
I've worked with a codebase like this for a personal project a while ago. It's in C++, but if you're interested you can read more here. Notice how the server and the client are registering to certain events, which they will forward across.
I am writing a adapter around autofac, and need to provide an implementation of:
T ResolveSingleton<T>()
where this method will return an instance if and only if the type was registered with singleton lifetime, otherwise it will throw an error.
I am new to autofac and was wondering if there is a way to query the container for the registered lifetime of a type?
Thanks!
Looking at the Autofac source code, you'll can see that the implementation of SingleInstance is this:
public IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> SingleInstance()
{
RegistrationData.Sharing = InstanceSharing.Shared;
RegistrationData.Lifetime = new RootScopeLifetime();
return this;
}
So you'll have to check the ComponentRegistry for registrations matching those qualities.
public T ResolveSingleton<T>()
{
IComponentRegistration reg;
if (_context.ComponentRegistry.TryGetRegistration(new TypedService(typeof (T)), out reg))
{
if (reg.Lifetime is RootScopeLifetime && reg.Sharing == InstanceSharing.Shared)
return (T) _context.ResolveComponent(reg, Enumerable.Empty<Parameter>());
}
throw new Exception();
}
I'm working on trying to get an AsyncController to work in OrchardProject. The current version I'm using is 2.2.4.9.0.
I've had 2 people eyeball my code: http://www.pastie.org/2117952 (AsyncController) which works fine in a regular MVC3 vanilla application.
Basically, I can route to IndexCompleted, but I can't route to Index. I am going to assume i'm missing something in the Autofac configuration of the overall project.
I think the configuration is in the global.asax: http://pastie.org/2118008
What I'm looking for is some guidance on if this is the correct way to implement autofac for AsyncControllers, or if there is something/someplace else I need to implement/initialize/etc.
~Dan
Orchard appears to register its own IActionInvoker, called Orchard.Mvc.Filters.FilterResolvingActionInvoker.
This class derives from ControllerActionInvoker. At a guess, in order to support async actions, it should instead derive from AsyncControllerActionInvoker.
Hope this helps!
Nick
The Autofac setup looks ok, and as long as you can navigate to something I cannot say that your assumption makes sense. Also, the pattern you are using for initialization in global.asax is used by others too.
The AsyncController requires that async methods come in pairs, in your case IndexAsync & IndexCompleted. These together represent the Index action. When you say you can navigate to IndexCompleted, do you mean that you open a url "..../IndexCompleted"?
Also, and this I cannot confirm from any documentation, but I would guess that AsyncController requires that all actions are async. Thus, your NewMessage action causes trouble and should be converted to an async NewMessageAsync & NewMessageCompleted pair.
I did too needed to have AsyncController which I easily changed FilterResolvingActionInvoker to be based on AsyncControllerActionInvoker instead of ControllerActionInvoker.
But there was other problems because of automatic transaction disposal after completion of request. In AsyncController starting thread and the thread that completes the request can be different which throws following exception in Dispose method of TransactionManager class:
A TransactionScope must be disposed on the same thread that it was created.
This exception is suppressed without any logging and really was hard to find out. In this case session remains not-disposed and subsequent sessions will timeout.
So I made dispose method public on ITransactionManager and now in my AsyncController, whenever I need a query to database I wrap it in:
using (_services.TransactionManager) {
.....
}
new TransactionManager :
public interface ITransactionManager : IDependency, IDisposable {
void Demand();
void Cancel();
}
public class TransactionManager : ITransactionManager {
private TransactionScope _scope;
private bool _cancelled;
public TransactionManager() {
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
public void Demand() {
if (_scope == null) {
Logger.Debug("Creating transaction on Demand");
_scope = new TransactionScope(
TransactionScopeOption.Required,
new TransactionOptions {
IsolationLevel = IsolationLevel.ReadCommitted
});
_cancelled = false;
}
}
void ITransactionManager.Cancel() {
Logger.Debug("Transaction cancelled flag set");
_cancelled = true;
}
void IDisposable.Dispose() {
if (_scope != null) {
if (!_cancelled) {
Logger.Debug("Marking transaction as complete");
_scope.Complete();
}
Logger.Debug("Final work for transaction being performed");
try {
_scope.Dispose();
}
catch {
// swallowing the exception
}
Logger.Debug("Transaction disposed");
}
_scope = null;
}
}
Please notice that I have made other small changes to TransactionManager.
I tried the AsyncControllerActionInvoker route as well to no avail. I would get intermittent errors from Orchard itself with the following errors:
Orchard.Exceptions.DefaultExceptionPolicy - An unexpected exception was caught
System.TimeoutException: The operation has timed out.
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
at System.Web.Mvc.Async.ReflectedAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass3f.<BeginInvokeAsynchronousActionMethod>b__3e(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass37.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49()
NHibernate.Util.ADOExceptionReporter - While preparing SELECT this_.Id as Id236_2_, this_.Number as Number236_2_,...<blah blah blah>
NHibernate.Util.ADOExceptionReporter - The connection object can not be enlisted in transaction scope.
So I don't think just wrapping your own database calls with a transaction object will help. The innards of Orchard would have to modified as well.
Go vote for this issue if you want AsyncControllers supported in Orchard:
https://orchard.codeplex.com/workitem/18012
I've just read "Injecting Custom Logic in ADO.NET Data Services" and my next question is, How do you get your [WebGet] method to show up in the client-side proxy classes? Sure, I can call this directly (RESTfully) with, say, WebClient but I thought the strong typing features in ADO.NET Data Services would "hide" this from me auto-magically.
So here we have:
public class MyService : DataService<MyDataSource>
{
// This method is called only once to initialize service-wide policies.
public static void InitializeService(IDataServiceConfiguration config)
{
config.SetEntitySetAccessRule("Customers", EntitySetRights.AllRead);
config.SetServiceOperationAccessRule("CustomersInCity", ServiceOperationRights.All);
}
[WebGet]
public IQueryable<MyDataSource.Customers> CustomersInCity(string city)
{
return from c in this.CurrentDataSource.Customers
where c.City == city
select c;
}
}
How can I get CustomersInCity() to show up in my client-side class defintions?
When you see your Odata in browser, you will see link ...
e.g. http://localhost:1234/odataService.svc
just write your method name after the link
for your method it will be something like this...
http://localhost:1234/odataService.svc/CustomersInCity?city="London"
Making my first steps in RIA Services (VS2010Beta2) and i encountered this problem:
created an EF Model (no POCOs), generic repository on top of it and a RIA Service(hosted in an ASP.NET MVC application) and tried to get data from within the ASP.NET MVC application: worked well.
Next step: Silverlight client. Got a reference to the RIAService (through its context), queried for all the records of the repository and got them into the SL application as well (using this code sample):
private ObservableCollection<Culture> _cultures = new ObservableCollection<Culture>();
public ObservableCollection<Culture> cultures
{
get { return _cultures; }
set
{
_cultures = value;
RaisePropertyChanged("cultures");
}
}
....
//Get cultures
EntityQuery<Culture> queryCultures = from cu in dsCtxt.GetAllCulturesQuery()
select cu;
loCultures = dsCtxt.Load(queryCultures);
loCultures.Completed += new EventHandler(lo_Completed);
....
void loAnyCulture_Completed(object sender, EventArgs e)
{
ObservableCollection<Culture> temp=
new ObservableCollection<Culture>loAnyCulture.Entities);
AnyCulture = temp[0];
}
The problem is this: whenever i try to edit some data of a record (in this example the first record) i get this error:
This EntitySet of type 'Culture' does not support the 'Edit' operation.
I thought that i did something weird and tried to create an object of type Culture and assign a value to it: it worked well!
What am i missing? Do i have to declare an EntitySet? Do i have to mark it? Do i have to...what?
Thanks in advance
It turns out that in the DomainService class one has to implement (or at least to mark "placeholder methods") as "Edit", "Delete",... eg
[Delete]
public void DeleteCulture(Culture currentCulture)
{
throw new NotImplementedException("UpdateCulture not Implemented yet");
}
[Insert]
public void InsertCulture(Culture newCulture)
{
throw new NotImplementedException("InsertCulture not Implemented yet");
}
This way the OrganizationDomainContextEntityContainer class creates an EntitySet with parameter EntitySetOperations.All (meaning that all the CUD operations are available).
Hope it's useful for someone in the future!