Re: [topshelf-discuss] Where are the ServiceConfigurator extension methods in version 3.1.1?

1,268 views
Skip to first unread message

Travis Smith

unread,
Mar 27, 2013, 12:05:49 PM3/27/13
to topshelf...@googlegroups.com
This looks correct. Does it build? Does it run? It might just be Intellisense is confused. 

Chris, you haven't changed anything here, right? I don't recall any changes that would make me thing this would change but I haven't been paying that close of attention. 

-Travis


On Tue, Mar 26, 2013 at 11:19 AM, Otto Dandenell <ottom...@gmail.com> wrote:
Hi,
 
I am attempting to build my first Topshelf windows service.
 
I am on Windows 7 64 bit, using Visual Studio 2012.
 
Downloaded Topshelf 3.1.1 using NuGet.
 
Here is my code:
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
 
 
namespace TopShelfMeddelandeConsumerService
{
	public class TavlingsmeddelandeConsumerService 
	{
		private Timer timer = null;
		private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
 
		public TavlingsmeddelandeConsumerService()
		{
			double interval = 5;
			timer = new Timer(interval);
			timer.Elapsed += new ElapsedEventHandler(OnElapsedInterval);
		}
 
		protected virtual void OnElapsedInterval(object sender, ElapsedEventArgs e)
		{
			log.Debug("Tick:" + DateTime.Now.ToLongTimeString());
		}
 
		public void Start()
		{
			log.Info("SampleService is Started");
 
			timer.AutoReset = true;
			timer.Enabled = true;
			timer.Start();
		}
 
		public void Stop()
		{
			log.Info("SampleService is Stopped");
 
			timer.AutoReset = false;
			timer.Enabled = false;
		}
	}
}
 
And then:
 
using System;
using System.IO;
using Topshelf;
using Topshelf.ServiceConfigurators;
 
namespace TopShelfMeddelandeConsumerService
{
	public class Program
	{
		static void Main(string[] args)
		{
			var host = HostFactory.New(hostConfigurator =>
			{
				hostConfigurator.Service<TavlingsmeddelandeConsumerService>(serviceConfigurator =>
					{
						// THIS DOES NOT GIVE ME TAB COMPLETION:
						serviceConfigurator.ConstructUsing(name => new TavlingsmeddelandeConsumerService());
					});
				
//				x.SetServiceName("FogisTavlingsmeddelandemottagare");
				hostConfigurator.SetDescription("FOGIS tävlingsmeddelandemottagare.");
				hostConfigurator.SetDisplayName("FOGIS tävlingsmeddelandemottagare");
				hostConfigurator.StartAutomatically();
				hostConfigurator.RunAsNetworkService();
				hostConfigurator.UseLog4Net();
			});
		}
	}
}
 
The intellisense / tab completion suggests that I am using a Topshelf.Runtime.HostSettings object when I am acting on the serviceConfigurator.
But the service actually compiles.
 
Have I missed some crucial project configuration?
 
Cheers
 
/ Otto
 

--
You received this message because you are subscribed to the Google Groups "topshelf-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to topshelf-discu...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Otto Dandenell

unread,
Mar 27, 2013, 12:26:03 PM3/27/13
to topshelf...@googlegroups.com
It does build.

It just had me frustrated for a long while as I was wondering if the API
had changed since the examples I was looking at were authored.

Thanks

/ Otto
> hostConfigurator.SetDescription("FOGIS t�vlingsmeddelandemottagare.");
> hostConfigurator.SetDisplayName("FOGIS t�vlingsmeddelandemottagare");
> hostConfigurator.StartAutomatically();
> hostConfigurator.RunAsNetworkService();
> hostConfigurator.UseLog4Net();
> });
> }
> }
> }
>
>
>
> The intellisense / tab completion suggests that I am using a
> Topshelf.Runtime.HostSettings object when I am acting on the
> serviceConfigurator.
> But the service actually compiles.
>
> Have I missed some crucial project configuration?
>
> Cheers
>
> / Otto
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "topshelf-discuss" group.
> To unsubscribe from this group and stop receiving emails from it,
> send an email to topshelf-discu...@googlegroups.com
> <mailto:topshelf-discuss%2Bunsu...@googlegroups.com>.

Chris Patterson

unread,
Mar 28, 2013, 7:56:32 PM3/28/13
to topshelf...@googlegroups.com
There should have been on namespace or API changes between 3.1 and 3.1.1 - the new version only contains a few fixes.

Jesse Beard

unread,
Apr 5, 2013, 4:03:50 PM4/5/13
to topshelf...@googlegroups.com
Not sure if you are using Resharper, but every so often I will need to empty it's caches to prevent false negatives with Intellisense where things compile but methods, extensions, etc. are red indicating errors but really there is none.
>                                         hostConfigurator.SetDescription("FOGIS t�vlingsmeddelandemottagare.");
>                                         hostConfigurator.SetDisplayName("FOGIS t�vlingsmeddelandemottagare");

Chris Patterson

unread,
May 13, 2013, 12:54:03 PM5/13/13
to topshelf...@googlegroups.com
Are you missing a using statement that is present in the example?



On Mon, May 13, 2013 at 5:30 AM, Josh <unique...@gmail.com> wrote:

I am facing the same issue and the code does not build. It works if I use the TownCrier class. Strangely, the intellisense changes and it does not work for any other class. I don't understand why and it's really hard because I can't express my problem and even search on google.
I've used Topshelf before and I've never faced this issue before. I think this has something to do with the latest version. 

To reproduce this : 
  1. Add a reference to TopShelf through Nuget. 
  2. Simply copy/paste the example code from the "Show me the code" section in the topshelf documentation, 
  3. change the class from TownCrier to something else and it does not build. 
I am using Visual Studio 2012 with Update 2. Tried building with .Net 4.0/4.5. Same problems in both. 

Any help would be appreciated.

Thanks.

MikeO

unread,
May 13, 2013, 5:33:52 PM5/13/13
to topshelf...@googlegroups.com
Having a hard time figuring out what makes this code work. If I cut-n-past the example from the 3.0 documentation - it works, however, I get no intellisense on the ServiceConfigurator extension methods. Well, perhaps that's because the parameter on HostFactory.Run is actually a "HostConfigurator" - not a "ServiceConfigurator" for which the "WhenStarted" extension methods are actually defined....

So, Intellisense can't figure this out - how am I supposed to?

WTF (do you think we have enough overloads on this?????)
        public static HostConfigurator Service<T>(this HostConfigurator configurator) where T : class, ServiceControl, new();
        public static HostConfigurator Service<TService>(this HostConfigurator configurator, Action<Topshelf.ServiceConfigurators.ServiceConfigurator<TService>> callback) where TService : class;
        public static HostConfigurator Service<T>(this HostConfigurator configurator, Func<T> serviceFactory) where T : class, ServiceControl;
        public static HostConfigurator Service<T>(this HostConfigurator configurator, Func<Topshelf.Runtime.HostSettings, T> serviceFactory) where T : class, ServiceControl;
        public static HostConfigurator Service<T>(this HostConfigurator configurator, Func<T> serviceFactory, Action<Topshelf.ServiceConfigurators.ServiceConfigurator> callback) where T : class, ServiceControl;
        public static HostConfigurator Service<TService>(this HostConfigurator configurator, Func<Topshelf.Runtime.HostSettings, TService> serviceFactory, Action<Topshelf.ServiceConfigurators.ServiceConfigurator> callback) where TService : class, ServiceControl;




            HostFactory.Run(x =>
            {
                
                x.Service<TownCrier>(svc =>                        //2
                {
// Added 2 lines
                    Console.WriteLine(s.GetType());   //   actually at runtime this is a DelegateServiceConfigurator....
                    var s = (ServiceConfigurator<TownCrier>) svc;  // Explicit cast - now I can see the extension methods...
                    s.ConstructUsing(name => new TownCrier());   //3
                    s.WhenStarted(tc => tc.Start());             //4                    
                    s.WhenStopped(tc => tc.Stop());              //5
                });
                x.RunAsLocalSystem();                            //6

                x.SetDescription("Sample Topshelf Host");        //7
                x.SetDisplayName("Stuff");                       //8
                x.SetServiceName("stuff");                       //9

				hostConfigurator.SetDescription("FOGIS tävlingsmeddelandemottagare.");
				hostConfigurator.SetDisplayName("FOGIS tävlingsmeddelandemottagare");
				hostConfigurator.StartAutomatically();
				hostConfigurator.RunAsNetworkService();
				hostConfigurator.UseLog4Net();
			});
		}
	}
}
 

Dru Sellers

unread,
May 13, 2013, 6:04:36 PM5/13/13
to topshelf...@googlegroups.com
Just curious, did chris' suggestion about usings help or make sense?

-d


--

Mike O'Shea

unread,
May 13, 2013, 8:16:56 PM5/13/13
to topshelf...@googlegroups.com

Thel example code in Git - just has the "using Topshelf;" statement at the top. Which I have in my code. 

No, the problem is that ServiceConfiguratorExtensions defines WhenStarted as an extension method on ServiceConfigurator<T>, which is an interface that also defines WhenStarted - kind of strange.

I've just started to unwind this code. It kind of looks like the tangle of interface definitions conflict with the extension methods and Visual Studio just trows it hands up and says "meh" 

Travis Smith

unread,
May 13, 2013, 8:26:51 PM5/13/13
to topshelf...@googlegroups.com, topshelf...@googlegroups.com
I dunno, the fact you are using an explicit cast makes me thing something is wrong. 

Do you have a solution that we could take a look at? It works on my machine, but that's not much help for you. 

-Travis

MikeO

unread,
May 13, 2013, 9:07:06 PM5/13/13
to topshelf...@googlegroups.com
I just created a new console application, added Topshelf via Nuget package manager (Topshelf 3.1.107) , then cut-n-pasted the example code from the 3.0 documentation into the Program.cs.
Then, Ctrl-. to add using Topshelf; to the top.

Code runs fine - F5.

However, the intellisense doesn't work - doesn't show WhenStarted, etc. on the l;ambda parameter for Service<T>( s =>....

If I hover over the lambda parameter for Service<T>( s => .. I notice that intellisense thinks it is a Topshelf.Runtime.HostSettings type.
So, that's probably due to the possibly ambiguous set of extension methods defined against HostConfigurator which is the outer 'x' lambda parameter on HostFactory.Run( x => ...
One of these extension methods (the first one according to VS) ...has HostConfigurator as a possible parameter, the others have ServiicConfigurator as a parameter, but with a callback.

Well, I kind of question why we'd be making such extensive use of (pun intended) of extension methods in a class library we have full control of?  Why not define these methods on the interfaces to begin with?
Oh, right, we do, but we also have them as extension methods....



Travis Smith

unread,
May 13, 2013, 10:04:20 PM5/13/13
to topshelf...@googlegroups.com
To be honest, here you're asking for help and I feel like you're being rather rude about the whole thing. It's not really making me drum up a whole lot of interest in helping you. 

Brand new solution C# console solution. Imported Topshelf via NuGet. I get intellisense pasting your code in. http://cl.ly/image/0U0i2e3S0E46 What version of VS are you using? Are you using CodeRush or ReSharper? Any other plugins? 



-Travis


Josh

unread,
May 14, 2013, 3:48:27 AM5/14/13
to topshelf...@googlegroups.com
Hi Chris & Travis,
Thank you for this great work that you have done and thanks for patiently spending time in helping.

Please have a look at this screenshot :




This only happens when I change the class from TownCrier to clsMyClass. Any idea why this happens?

Thanks.

Travis Smith

unread,
May 14, 2013, 7:35:20 AM5/14/13
to topshelf...@googlegroups.com
Can you post the entire source? Does your service implement Start and Stop methods?

-Travis

Chris Patterson

unread,
May 14, 2013, 11:48:10 AM5/14/13
to topshelf...@googlegroups.com
A common pattern since the introduction lambda methods to C# is to provide overloads that support additional lambda signatures beyond the most explicit signature used by the interface. This way, implementors of the interface don't have to implement all the "pointer methods" that simply call the most explicit version of the method with everything else ignored. My guess is that you are not using a compatible signature in some way.

There are two WhenStarted methods, one that accepts a simple (service) => service.Start signature, and another that accepts a more verbose (service, hostSettings) signature, providing additional information about the host.

If there is some issue with these not resolving via Intellisense properly, well, I didn't write intellisense so I can't explain that one. I haven't noticed anything unusual but will try to remember to take a look and see if there is a namespacing issues or something.

MikeO

unread,
May 14, 2013, 1:23:35 PM5/14/13
to topshelf...@googlegroups.com
Sorry if I'm coming off rude, and thanks for trying to help.
This is vs2012 11.0.51106.01 Update 1. The Intellisense is getting confused because of the reason stated previously.
So far as getting the intellisense working - casting the lambda parameter to ServiceConfigurator will get the job done, but it's not really an ideal fix - and honestly - if I know enough about the API to do that I probably don't need intellisense :)

But, I'm concerned about new users to this API - and if they don't have intellisense, they have to work a lot harder to use the API

The fix IMHOP would be to look at the extension methods, possibly fold them into the interface definition so any ambiguity can be resolved at compile time, and then intellisense would work and the code could be improved.

Travis Smith

unread,
May 14, 2013, 2:49:09 PM5/14/13
to topshelf...@googlegroups.com
The WhenStart on the ServiceConfigurator<T> is what does the actual configuration. The extension methods are connivence methods (https://github.com/Topshelf/Topshelf/blob/master/src/Topshelf/Configuration/ServiceConfiguratorExtensions.cs#L43). It also makes it so it's easy to layer on additional configuration / implementations. This is key to us being able to readdress shelving at some point. 



-Travis

Josh

unread,
May 15, 2013, 8:40:37 AM5/15/13
to topshelf...@googlegroups.com
Hello,
I've attached a sample project here. However, I am unable to reproduce the same error on this project even if I change the class name. But, I can reproduce it if I touch anything within the Lambda expressions


Thanks. 
ConsoleApplication16.rar

Stuart Dunkeld

unread,
May 15, 2013, 10:17:17 AM5/15/13
to topshelf...@googlegroups.com
You need to remove the line s.CanPauseAndContinue = true; as CanPauseAndContinue has no setter.

Regards

--stuartd

MikeO

unread,
May 15, 2013, 11:32:50 PM5/15/13
to topshelf...@googlegroups.com
This is so strange. I've have done this - including opening your attached project - in VS2012 11.0.xx Update 1 - on two different machines.
In every case, I do not get intellisense on the 's' lambda parm following Service<clsMyClass>. 

I still think it's because VS2012 (this update) is getting confused about the extension methods that take Action<> and Func<> as their first parms. Now, yes, this is probably more a VS2012 issue. However, if it's confusing to VS2012, it's probably confusing to people too.

MikeO

unread,
May 15, 2013, 11:35:34 PM5/15/13
to topshelf...@googlegroups.com
I'm not sure I understand that, but I'll try. I think this may be a vs2012 (update 1) issue. The compiler understands this. Intellisense does not. However, I still think there's a code smell here. I guess I'll just do the pull request and speak in code on the subject from this point forward ;)

Josh

unread,
May 16, 2013, 7:17:20 AM5/16/13
to topshelf...@googlegroups.com
Stuard,Travis and Chris,
Did you notice the multiple compiler errors in my project that I attached previously? I agree I'm setting a readonly property there but please understand ...the issue is not about the readonly property. If it is about just the readonly property, it should display only one compiler error right? 
Please see that it displays multiple compiler errors. This happens for any modification to that piece of code.

Thanks,
Josh

Stuart Dunkeld

unread,
May 16, 2013, 8:16:34 AM5/16/13
to topshelf...@googlegroups.com
Josh,

Now I see the problem. You can work round it by configuring the service in a method: then intellisense knows what the relevant type is and all is well.

        static void Main(string[] args)
        {
            HostFactory.Run(ConfigureHost);
        }

        private static void ConfigureHost(HostConfigurator x)
        {
            x.Service<clsMyClass>(ConfigureService);


            x.SetDescription("Sample Topshelf Host"); //7
            x.SetDisplayName("Stuff"); //8
            x.SetServiceName("stuff"); //9
        }

        private static void ConfigureService(ServiceConfigurator<clsMyClass> s)
        {
            s.ConstructUsing<clsMyClass>(name => new clsMyClass()); //3

            s.WhenStarted(tc => tc.Start()); //4
            s.WhenStopped(tc => tc.Stop());           
        }

Louis-Philippe Meunier

unread,
Jan 19, 2015, 11:13:05 AM1/19/15
to topshelf...@googlegroups.com
I know this post is old and all, but this is happening to me right now.

Brand new console project, added nuget,following example on the site doesn't work. I do not get the intellisense but writing the extension methods directly does compile.

Is there a resolution for this issue?

VS 2013 (12.0.31101.00 update 4)
Reply all
Reply to author
Forward
0 new messages