Remember when I introduced you to the Search References extension? I know my fellow coworkers at Clarius are awesome and all, but I was happily surprised when after installing MonoDroid, the following just worked:
See the "Filtered to: MonoDroid Profile"? See how the paths point to the right assemblies under MonoDroid reference assemblies?
Kudos to the http://go-mono.com/monodroid/ team for integrating so nicely in the VS2010 environment!
Most online radios stream using ASX and WMA encoding, which doesn't work in Android phones at all.
I was even going to go for a homebrew "server" using VLC which can transcode. But that would mean I need to keep a machine up all the time, take care of keeping the process up, opening firewall ports, etc. etc.
After a bit of research, I found a pretty acceptable solution for the time being:
- Create an account and sign in at http://www.yourmuze.fm/. Select your preferred streaming audio quality.
- First, in Stations, you can search for an existing radio if it's already there.
- The one I was looking for wasn't there, so I clicked on "add a new station". Here you'd enter the mms:// or http:// stream address.
- After you create the station, it's not automatically added to your "My Stations" queue. But it will be the first station in the list now:

- Click the "add" link to the right of the station name, in the My Stations column. You're done with the site.
- In phone, go to http://m.yourmuze.fm/ and log in. Under My Stations you will find yours.
Opening it will launch the video player tuned to the radio. This might seem like a minor issue, but it's not: videos run in full screen and NEED to be in the foreground, otherwise they are stopped. So no background playing radios! Bummer. This is a known issue that they will fix with an upcoming native app for Android. - To solve that issue, you need to install the Dolphin HD browser from the android market (free). It's a pretty interesting browser on its own. But I'm only interested in launching this one radio I care :).
- Go the Dolphin HD browser Settings, and set the User Agent to iPhone.
- If you want to launch the radios with one click, browse now to http://m.yourmuze.fm/, long-press the station from My Stations section, and select Bookmark link.
- Next go to Bookmarks (you can just swipe the screen to the right, very Metro!), click Edit, and long-press the station bookmark you just created and select Add shortcut to Home.
- Next you need an audio player that doesn't believe it's streaming video. The only one that worked for me is xiialive lite (free too). You don't need to do anything in the player.
Now the radio will be launched from the browser into the audio player automatically, in a format that is understood in Android :).
Enjoy!
/kzu
[to my English-only dear readers, this is going to be just Spanish, for my compatriots. I hope you don't mind :)]
Soy Abogado, al fin y al cabo. Y uno (el único?) realmente invicto: gane el 100% de mi/s juicio/s (fue UNO, pero muy importante para mi familia ;)). Y me pincharon donde más me duele: "investiga un poco primero antes de hablar".
Así que aquí va mi trabajito de unas horas de investigación y conclusiones sobre el tema.
Relación con fusión de Cablevisión y Multicanal
Algunos me argumentaron que el tema de la revocación de la licencia de Fibertel no tenía nada, pero *nada* que ver con la fusión de Cablevisión y Multicanal. Les recuerdo:
En 2002, la Inspección General de Justicia de la Nación aprueba la absorción societaria de Fibertel-Cablevisión. Después, Multicanal se fusiona con Cablevisión, que la IGJ aprueba en enero de 2009. Año y medio después, la SECOM revoca la licencia de Fibertel en la resolución 100/2010.
En los considerandos (los "que...") se nombran varios articulos del decreto 764/2000, mencionando tanto el art. 16.2.5 por la causal de "cesión o transferencia a terceros de la licencia o el cambio de control social, que no hubiera sido autorizada", como el 16.2.7 de caducidad por "quiebra, disolucion y/o liquidacion del prestador", que tiene tratamiento especial en el 16.3.2 que establece que "16.3.2 La declaración de caducidad con causa en la declaración de quiebra, disolución o liquidación de la sociedad será aplicable sin necesidad de requerimiento previo alguno."
Está claro que la autorización de la IGJ de una fusión no implica automáticamente una autorización de transferencia de licencia entre las compañías involucradas en lo que es un ámbito totalmente distinto y responsabilidad de la SECOM. Cablevisión parece estar claramente operando sin licencia.
Sin embargo, Cablevision esgrime que ya era la empresa controladora de Fibertel desde antes de la fusion, y por consiguiente no hubo cambio de titularidad. Esa parece ser la cuestion de fondo, y el error formal consecuente de no haber pedido la transferencia que como se nota en el siguiente apartado, es un tramite que no reviste mayor complejidad.
El gobierno quiere interpretar la norma en el sentido de que se trata de "caducidad con causa en la declaracion de quiebra, disolucion o liquidacion", una prevision que a mi entender se refiere a casos en que la empresa en cuestion desaparece de la faz de la tierra. Sin embargo, al tambien mencionar el articulo sobre "cesión o transferencia...que no hubiera sido autorizada" deja entrever el principal conflicto de su postura: puede interpretarse la aplicabilidad de una o la otra! Como muchas cosas en Derecho, efectivamente la interpretacion de las normas es un paso esencial al aplicarlas.
Y respecto a ello, la Ley Nacional de Procedimientos Administrativos establece en su Articulo 1:
Informalidad
c) Excusación de la inobservancia por los interesados de exigencias formales no esenciales y que puedan ser cumplidas posteriormente;
Asi que analicemos la importancia de la licencia, los requisitos de su emision, y si estamos ante una falta grave que amerita una sancion extrema y una disrupcion importante para los usuarios, o si estamos ante una exigencia formal no esencial que podria resolverse de alguna manera menos conflictiva.
Magnitud de la importancia de la licencia
Ahora, otro argumento esgrimido fue sobre lo grave de operar sin licencia, y como "no cualquiera" puede obtener una.
Veamos primero lo que debería haber hecho Cablevisión para obtener la transferencia o cesión de la licencia, establecido en el decreto 764/2000 citado por el gobierno mismo como causal de caducidad:
Artículo 13. Cesión o transferencia de la licencia
13.1 El Prestador podrá ceder o transferir la licencia, previa autorización de la Autoridad de Aplicación, la que no le podrá ser denegada si el Prestador transferente o cedente:
i) no registra deuda alguna con el Estado Nacional en concepto de: ...
ii) ha realizado las inversiones previstas en el inciso f) del apartado 10.1. del presente Reglamento;
iii) ha cumplido con los compromisos asumidos con el Estado Nacional relacionados con la prestación del servicio de telecomunicaciones; y
iv) ha dado cumplimiento a los requisitos y/o condiciones que su título original impone a la cesión o transferencia de su licencia, en caso de corresponder;
v) ha obtenido, en su caso, la autorización para la transferencia de la autorización y/o permiso de uso de frecuencias radioeléctricas en los términos de la reglamentación correspondiente; y siempre que el Prestador cesionario:
a) hubiera presentado la información requerida por el apartado 9.1. el presente Reglamento.
b) manifieste y acepte, bajo declaración jurada, que conoce y se obliga a cumplir todas las obligaciones asumidas por el Prestador cedente, con motivo de la licencia objeto de la cesión.
13.2. La Autoridad de Aplicación deberá expedirse, respecto de la solicitud de cesión o transferencia de la licencia, dentro del plazo de sesenta (60) días, contados a partir de la fecha de presentación de la misma.
Básicamente un libre deuda y una declaración jurada de continuar con las obligaciones del cedente.
Podría argumentarse que en realidad es MUCHO más que eso, y que, de nuevo, "no cualquiera" puede obtener una licencia nueva. La página de la CNC donde se detallan los requisitos es casi irrisoria para la envergadura que le dio el gobierno al problema y la sanción aplicada. Sí, yo creo que hasta Clarius podría conseguir esa licencia en tiempo record (dicen que solo cuesta ARS/$ 2000). Y sin ánimo de ofender a ninguno en particular, basta mirar la lista de prestadores para darse cuenta de que está MUY lejos de ser rocket-science.
Así que sigo sin entender como espera el gobierno que creamos que nos están salvando de un delincuente peligrosísimo (en vez de ocuparse de los delincuentes de verdad, alguno podría agregar).
El gobierno en su evaluacion de la gravedad de no haber pedido tal transferencia, dice:
...sobre todo cuando lo que se encuentra bajo tutela regulatoria fuera otorgado "intuito personae", ya que debe necesariamente corroborarse que en los cambios de control social y/o en las transferencias se cumplen los requisitos de especialidad contemplados en la ley, o que las modificaciones introducidas no alteran la especie y no desvirtuan las condiciones del otorgamiento.
En el articulo anterior sobre requisitos para la transferencia, salvo el apartado sobre inversiones y sobre continuar con lo ya comprometido como servicio, no parece haber ninguna otra causal para impedirla. De vuelva, parece una mera cuestion formal, si los requisitos basicos (bastante elementales) se cumplen. Y en tal caso, la peticion no le podrá ser denegada, tal como dice la misma reglamentacion.
Ahora, hay al menos dos grandes razones por las que creo que el gobierno va a estar en problemas en la justicia: proporcionalidad de la sanción, y fallas de procedimiento.
Hubo sanción?
Alguno sugirio que en realidad no hubo sanción, sino que simplemente la licencia dejo de existir porque la empresa licenciataria dejo de existir. El articulo 16.2.7 de la resolucion 764/2000 citada como causal (pagina 6 de la resolucion 100) esta expresamente en la seccion sobre sanciones:
Artículo 16. Sanciones. Condiciones de caducidad de las licencias.
16.2.7 Quiebra, disolución y/o liquidación del Prestador.
Bastante claro para mi que se trata de una sanción. Para abundar, la misma resolucion del gobierno agrega (pagina 5):
Que la sanción prevista en razon del incumplimiento mencionado es la declaracion de la caducidad de la Licencia y los registros de los servicios.
Claramente estamos hablando de una sancion.
Proporcionalidad de la sanción
Creo que hay grandes chances de que la justicia falle en contra del gobierno (o sea VOS Y YO con nuestros impuestos). La principal razón es la Ley Nacional de Procedimientos Administrativos, y que indica claramente:
Requisitos esenciales del acto administrativo.
ARTICULO 7. Son requisitos esenciales del acto administrativo los siguientes:
Finalidad.
f) habrá de cumplirse con la finalidad que resulte de las normas que otorgan las facultades pertinentes del órgano emisor, sin poder perseguir encubiertamente otros fines, públicos o privados, distintos de los que justifican el acto, su causa y objeto. Las medidas que el acto involucre deben ser proporcionalmente adecuadas a aquella finalidad.
Está claro entonces que es indispensable la proporcionalidad entre la sanción y la infracción. Las sanciones posibles a aplicar por parte de la CNC/SECOM están estipuladas en el decreto 1185/90, que contempla:
Art. 38.- SANCIONES
a) Las sanciones consistirán en apercibimientos, multas, caducidad total o parcial del régimen de exclusividad cuando lo hubiere, y caducidad de la licencia, autorización o permiso.
b) Las sanciones se graduarán en atención a:
1) La gravedad y reiteración de la infracción.
2) Las dificultades o perjuicios que la infracción ocasione al servicio prestado, a los usuarios y a terceros.
3) El grado de afectación del interés público.
4) El grado de cumplimiento de las metas obligatorias y no obligatorias y demás condiciones fijadas en la licencia o permiso respecto del servicio en cuestión, si las hubiere.
Del articulo a) se desprende que la sanción aplicada por la SECOM es la MAXIMA permitida por la reglamentación vigente. Y yo me pregunto cómo es justificable la proporcionalidad de esa medida en el caso de una empresa de reconocida trayectoria como Fibertel (y Cablevisión) que ofrece un servicio donde la gran mayoría de los usuarios están satisfechos (mucho más satisfechos que yo por ejemplo con Telefónica/Speedy) y donde parece totalmente ausente un grave perjuicio al interés público, a los usuarios, a terceros o al servicio mismo.
d) La aplicación de sanciones será independiente de la obligación de reintegrar o compensar las tarifas indebidamente percibidas de los usuarios, con actualización e intereses, o de indemnizar los perjuicios ocasionados al estado, a los usuarios o a terceros por la infracción.
Por supuesto que corresponde la aplicación de multas por la infracción, no hay discusión al respecto.
Fallas de procedimiento
De igual relevancia, es la desprolijidad con la que el gobierno manejo este tema, para lograr un efecto "sorpresa" o no sé bien que.
La Ley Nacional de Procedimientos Administrativos ya citada, determina el procedimiento para declarar la caducidad del acto administrativo (la otorgación de la licencia a Fibertel):
Caducidad.
ARTÍCULO 21.- La Administración podrá declarar unilateralmente la caducidad de un acto administrativo cuando el interesado no cumpliere las condiciones fijadas en el mismo, pero deberá mediar previa constitución en mora y concesión de un plazo suplementario razonable al efecto.
A lo que se suma el decreto q crea la CNC y reglamenta su funcionamiento y atribuciones (http://www.infoleg.gov.ar/infolegInternet/anexos/0-4999/3647/norma.htm), q dice:
Art. 25.-
CADUCIDADES.
La declaración de caducidad de las licencias, autorizaciones o permisos por el PODER EJECUTIVO NACIONAL o la Comisión Nacional de Telecomunicaciones, según el caso, se sujetará a las reglas del debido proceso adjetivo, en particular las contenidas en la Ley de Procedimientos Administrativos y su reglamentación.
Rematado por el artículo de sanciones:
Art. 38.-
SANCIONES
h) En la aplicación de las sanciones se seguirá el procedimiento que establezca al respecto la Comisión Nacional de Telecomunicaciones el que deberá asegurar el derecho de defensa del imputado. A tales efectos deberá notificársele la imputación y otorgársele un plazo no inferior a DIEZ (10) días hábiles administrativos para la producción del descargo pertinente.
Todo este asunto suena a tirado de los pelos, desproporcionado y desprolijo, tal como se hizo con la Ley de Medios en su momento tambien. Y esto explota justo días después de la famosa cena de Magneto contra el gobierno. Feliz coincidencia!
¡Vanidad, pura vanidad!
It's been a long time since our last post. I just wanted to let you know about the amazing progress we've been making on Visual T4 for VS2010. What's new in short? A major overhaul to take full advantage of all the benefits of the brand new WPF-based core text editor as well as the new language services to provide the absolutely unique and long-time praised Intellisense integration.
We'll go into the details on another post, but here's a bunch of screenshots to get you excited, using the ADO.NET C# POCO Entity Generator templates.
Colors honor your favorite C# editor settings:
Tooltips as usual in C#:
Intellisense on APIs as usual in C#:
Parameter info as usual in C# code :)
Pretty good indenting!
Full support for VERY complex includes! (the EF one has 2200+ lines)
Full T4 directives intellisense with tooltips, as you'd expect:
Can add arbitrary assemblies an get their intellisense too:
Can build any LINQ query you fancy with full intellisense:
Use your favorite code snippets as usual in C#:
With even full anonymous types support:...
Read full article
At Clarius we've spent years doing Visual Studio extensibility. Literally. We LOVE doing so. We did so much of it during the years that chances are pretty high you've been using some of our stuff (fully or partially developed by us) at one point or another. A non-exhaustive list includes:
In my opinion, Visual Studio 2010 marks a significant milestone in making the platform *easily* extensible. We can thank MEF for a lot of that.
So we wanted to do something to help foster the developer community by giving everyone a central place where suggestions for improvements to VS can be made. Having a single place where Visual Studio Extensibility enthusiasts can lookup ideas for a weekend's pet project, or where big companies (including Microsoft!) can look for future product features and improvements, is definitely valuable.
But we wanted to go further. We also want to be an actual development arm that brings the best ideas to fruition. We will be actively picking up ideas and implementing them for your enjoyment. Search References is one example, with many more on the way.
I sincerely look forward to the World of VS to become your world too. We have a much bigger vision for it that we'll be sharing over time, but I think this is already an exciting beginning!
And just to make it a tad more interesting and engaging at launch time, we're giving away a FULL MSDN Universal subscription to the most voted idea! Go ahead and share with the world your biggest pain or your crazy idea for VS2010!
/kzu
I am pleased to announce that StickyNotes version for Visual Studio 2010 is now available.
I like to invite you to try this version of the product, and experience the updated interface and new features.
Why should you try it:
- Visual Studio 2010 support with a new updated user interface
- *new* Support for VC++ projects
- Create notes from Visual Studio tasks
- Create notes from compiler, FxCop and StyleCop warnings
- Convert notes to Visual Studio tasks
- Email notes
- Edit in place
You can download it from here
Please try it out and don’t forget to send feedback
Pablo
Today I received the confirmation email. I am a MVP again for Visual C#.
I want to thank my MVP lead Fernando Garcia Loera and the rest of people involved in the evaluation process for the recognition of my community efforts.
Thanks Microsoft!!!
Pablo
The new Visual Studio 2010 Pro Power Tools bring a new Add Reference dialog that completely replaces the classic one when you click the familiar Add Reference command:
It seems like a nice dialog that is more aligned with the new Add New dialog and the Extension Manager one. But for this particular case, I believe it's awfully overkill (what's the use of that right sidebar? what's the use for the categories of assemblies split between Framework and Extensions?).
The (also new) Search References extension which I blogged about earlier, gives you the familiar classic dialog enhanced with the must-have Search capability:
![image[10]](http://www.clariusconsulting.net/images/blogs/kzu/d5a5f81701d1_9BFA/image10.png)
This dialog has a few key usability features that make it a snap to use (and better than the Pro Power Tools one, I think): it will open up focused on the search textbox, it will remember your last search, and it supports keyboard-only usage extensively (i.e., type "entity", down-arrow to enter the filtered list, shift or control multi-select, press Enter and done!). Also, as you're already used to, double clicking on a reference also directly adds it and dismisses the dialog (in the Pro Power Tools you need to close the dialog explicitly).
If you want to continue using this familiar, lightweight and simpler dialog, but still want to install the Pro Power Tools, you can easily disable its "Add Reference" dialog by going to your %LocalAppData%\Microsoft\VisualStudio\10.0\Extensions\Microsoft\Visual Studio 2010 Pro Power Tools folder, and deleting the AddReference.dll and AddReference.pkgdef files.
Enjoy!
If you have been using VS2010 for any significant amount of time, you surely came across the awkward, slow and hard to use Add Reference dialog. Despite some (apparent) improvements over the VS2008 behavior, in its current form it's even LESS usable than before. A brief non-exhaustive summary of the typical grief with this dialog is:
- Scrolling a list of *hundreds* of entries? (300+ typically)
- No partial matching when typing: yes, you can type in the list to get to the desired entry, but the matching is performed in an exact manner, from the beginning of the assembly name. So, to get to the (say) "Microsoft.VisualStudio.Settings" assembly, you actually have to type the first two segments in their entirety before starting to type "Settings".
- Lazy loading with no progress indicator: loading is done asynchronously in VS2010, supposedly improving the situation from VS2008 where it would just freeze until it was done. Well, without an indicator, you don't know when loading is done and when it's safe to assume a given assembly isn't there because it is truly not available.
- Random order while lazy loading: moreover, while the lazy loading is happening (and you don't know when it's done), entries in the list are added in an almost random order, so any scrolling or typing you do results in constant repositioning of the current selection and changes to the underlying list. This makes it effectively impossible to use the dialog until the lazy loading is completed.
- No sorting while lazy loading: related to the previous one, you cannot sort the list at all until the lazy loading is complete, so scrolling is impossible.
So we decided to do something about it. I introduce you to the Search References extension:
From the Extension Manager in Visual Studio 2010, you can simply search the Online Gallery for "Search Reference" and install it right-away:
The dialog loads VERY fast. And because a picture speaks a thousand words, here are more screenshots to get you excited.
Partial matching:
Multi-selection:
Current project .NET profile aware. Silverlight 4:
![image[23] image[23]](http://www.clariusconsulting.net/images/blogs/kzu/d5a5f81701d1_9BFA/image23.png)
Silverlight 3:
Enjoy, and don't forget to rate it!
In the latest and greatest version of Visual Studio, MEF plays a critical role, one that makes extending VS much more fun than it ever was.
So typically, you just [Export] something, and then someone [Import]s it and that's it. MEF in all its glory kicks in and gets all your dependencies satisfied.
Cool, you say, so let's now import ITextTemplating and have some T4-based codegen going! Ah, if only it was that easy. Turns out by default, none of the VS built-in services are exposed to MEF, apparently because there wasn't enough time to analyze the lifetime, initialization, dependencies, etc. for each one before launch, which makes perfect sense. You don't want to blindly export everything now just in case. There's also the whole VS package initialization thing which in this version of VS is not so transparently integrated with the MEF publishing side (i.e. a MEF export from a package can get instantiated before its owning package, and in fact, the package can remain unloaded forever and the export will continue to be visible to anyone).
So, you just have to calm down, and re-encounter "good"-old IServiceProvider. Turns out, that's still the "blessed" way to get your dependencies, but now you can get the service provider from MEF instead:
[ImportingConstructor]
public TextTemplate([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider)
Note that in typical VS fashion, the actual exported contract (interface) is SVsServiceProvider, which can be converted automatically to an IServiceProvider.
But, if you make your entire class just work off of this service locator (doing GetService here and there), you lose all the "explicit-ness" that comes from having a proper constructor that declares that this class needs, say, an ITextTemplating. This makes it much harder for consumers attempting to reuse the implementation to figure out what this component needs.
Fortunately, MEF does not require your importing constructors to be public, so you can provide the MEF-exclusive constructor as internal, and make the constructor with your explicit dependencies public:
[ImportingConstructor]
private TextTemplate([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider)
: this(serviceProvider.GetService<STextTemplating, ITextTemplating>())
{
}
public TextTemplate(ITextTemplating templating)
{
Guard.NotNull(() => templating, templating);
this.templating = templating;
}
Your tests will also instantiate this class exclusively from the non-MEF constructor, and pass moqs as needed. (note I'm using a simple generic GetService extension method on IServiceProvider to make code more concise).
/kzu
I have already written about other alternative ways of implementing INotifyPropertyChanged, as well as augment your view models with a bit of automatic code generation for the same purpose. But for some co-workers, either one seemed a bit too much :o).
So, back on the drawing board, we came up with the following view model authoring experience:
public class MyViewModel : ViewModel, IExplicitInterface
{
private int value;
public int Value
{
get { return value; }
set { this.value = value; RaiseChanged(() => this.Value); }
}
double IExplicitInterface.DoubleValue
{
get { return value; }
set { this.value = (int)value; RaiseChanged(() => ((IExplicitInterface)this).DoubleValue); }
}
}
You can see how raising property changed on a property is just a matter of passing an expression like "this.PropertyName" to the base RaiseChanged method. This is 100% refactoring friendly. No magic strings.
Also, we support raising a property changed for an interface that you implemented explicitly, like the second case.
The base class defines the RaiseChanged method as follows:
protected void RaiseChanged<TProperty>(Expression<Func<TProperty>> propertyExpresion)
Note how the TProperty type parameter can be completely omitted from the call to RaiseChanged() from the derived class, letting the compiler figure it out. The expression, being anything matching a Func<T>, could conceivable be an invalid reference to a property the object does not own, so we validate that in the method body by inspecting the expression tree:
protected void RaiseChanged<TProperty>(Expression<Func<TProperty>> propertyExpresion)
{
var property = propertyExpresion.Body as MemberExpression;
if (property == null || !(property.Member is PropertyInfo) ||
!IsPropertyOfThis(property))
{
throw new ArgumentException(string.Format(
CultureInfo.CurrentCulture,
"Expression must be of the form 'this.PropertyName'. Invalid expression '{0}'.",
propertyExpresion), "propertyBLOCKED EXPRESSION;
}
this.OnPropertyChanged(property.Member.Name);
}
We first ensure the expression references a member and that the member is actually a property. Next, the IsPropertyOfThis method verifies that the target of that property access is actually a reference to "this". This is kinda cool:
private bool IsPropertyOfThis(MemberExpression property)
{
var constant = RemoveCast(property.Expression) as ConstantExpression;
return constant != null && constant.Value == this;
}
We just look for a constant expression and compare its value to "this" :). For the explicitly implemented property case, there will be a cast before the reference to "this", so we remove it if necessary to get access to the constant:
private Expression RemoveCast(Expression expression)
{
if (expression.NodeType == ExpressionType.Convert ||
expression.NodeType == ExpressionType.ConvertChecked)
return ((UnaryExpression)expression).Operand;
return expression;
}
All in all, a fairly simple base class with a tiny bit of strong-typed help for raising notify property changed events for view models.
Next, we'll augment it with knowledge of IDataErrorInfo and System.ComponentModel.DataAnnotations attributes.
Full ViewModel class code available.
Enjoy!
public static IEnumerable<ValidationResult> Validate(object component)
{
return from descriptor in TypeDescriptor.GetProperties(component).Cast<PropertyDescriptor>()
from validation in descriptor.Attributes.OfType<System.ComponentModel.DataAnnotations.ValidationAttribute>()
where !validation.IsValid(descriptor.GetValue(component))
select new ValidationResult(
validation.ErrorMessage ?? string.Format(CultureInfo.CurrentUICulture, "{0} validation failed.", validation.GetType().Name),
new[] { descriptor.Name });
}
Enjoy!
Something we've been doing in moq since the very beginning is to have a single assembly as output: Moq.dll. This reduces the clutter for users and lets them focus on what they need from our library, rather than getting the noise of whatever third-party (or internal) libraries we use to implement it.
This is good from the deployment point of view too, and if all your libraries are actually internal infrastructure assemblies, you can even make them all internal types of your output assembly.
The key to all this is ILMerge, and it's very easy to setup in a project. You just need to download the installer, copy the included executable somewhere (i.e. "Tools") near your project and reference it from a post-build task in the project. The following configuration merges all referenced assemblies that have "Copy Local" set to true into the output assembly, and internalizes all the types in those libraries (makes them all internal to the output assembly), except for those in the optional (can be empty) exclude file (which can contain a full type name per line, to leave their visibility untouched):
<target name="AfterBuild" condition=" '$(Configuration)' == 'Release' ">
<createitem include="@(ReferenceCopyLocalPaths)" condition="'%(Extension)'=='.dll'">
<output itemname="AssembliesToMerge" taskparameter="Include" />
</createitem>
<exec command=""$(MSBuildProjectPath)..\..\..\..\Tools\ILMerge.exe" /internalize:"$(MSBuildProjectPath)ilmerge.exclude" /ndebug /keyfile:$(AssemblyOriginatorKeyFile) /out:@(MainAssembly) /targetplatform:v4,$(MSBuildToolsPath) "@(IntermediateAssembly)" @(AssembliesToMerge->'"%(FullPath)"', ' ')" />
<delete files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
</target>
After merging the assemblies (only for release builds, in this case), it will delete the embedded assemblies.
Enjoy!
Update: turns out I had blogged about this before more extensively :).
I've grown a bit tired of implementing INotifyPropertyChanged. I've tried ways to improve it before (like this "ViewModel" custom tool which even generates strong-typed event accessors).
But my fellow Clarius teammate Mariano thought it was overkill and didn't like that tool much. He mentioned an alternative approach also, which I didn't like too much because it relied on the consumer changing his typical interaction with the object events, but also because it has a substantial design flaw that causes handlers not to be called at all after a garbage collection happens. A very simple unit test will showcase this bug.
I also looked at the new WeakEvent Patterns page in MSDN but it's even worse in terms of implementing and exposing it to consumers.
So, with my ever growing love for lambdas and my strong-typed reflection approach (used by the first alternative too, btw), I thought I could do better :). Here's the result of that, which I think improves all the above choices.
Why you need weak reference support
The importance of this cannot be understated. A delegate that you pass around has a strong reference to the instance that exposes it. This is the Target property on the delegate class. What this means is that even if the subscribing object goes out of scope and is ready to be collected, it will not be as long as the event source (the object exposing the PropertyChanged event, for example) holds a reference to it. And as long as the event subscription is there, the reference will be there too. That's why it is typically important to remove your reference once you're ready to "go" (i.e. on Dispose, you detach from the events you're listening). Needless to say, this is a repetitive, error-prone activity.
Another typical side-effect of this is that you cannot use anonymous delegates or lambdas if you need to unsubscribe, as you need to keep a reference to the originally subscribed lamdba in order to unsubscribe:
var target = new Foo();
target.PropertyChanged += (sender, args) => Console.WriteLine(args.PropertyName);
// How do you unsubscribe now??
// This clearly doesn't work because even if the actual source is the same,
// the delegate is still a brand-new one.
target.PropertyChanged -= (sender, args) => Console.WriteLine(args.PropertyName);
// So you need to keep the lambda around:
PropertyChangedEventHandler handler = (sender, args) => Console.WriteLine(args.PropertyName);
// Just so you can use that to subscribe/unsubscribe:
target.PropertyChanged += handler;
target.PropertyChanged -= handler;
// So typically you're better off just adding a full instance method on your
// consumer just so you have a clear pointer for unsubscribing:
target.PropertyChanged += OnTargetPropertyChanged;
// But now if you need contextual state in the event handler that exists
// at subscription time, you need to promote that state to class fields
// so that you can use that in the event handler
this.someState = currentMethodState;
// This is looking like .NET 1.0 already ;)
The PropertyChangeManager way
I therefore decided to take a TDD approach to the issue with the following requirements:
- The programming model for consumers must not involve creating any new objects. They already have the object that will be raising property change events.
- The "old style" way of attaching to property changed events must still work, but add the weak reference support that's so badly needed. And this must be transparent to consumers.
- A new style should involve using lambdas to avoid property names as strings
- The new style should be trivial to implement for an author exposing INotifyPropertyChanged.
So I came up with these BDD-style test specifications:
- WhenSubscriberIsAlive_ThenNotifiesSubscriber
- WhenSubscriberIsNotAlive_ThenDoesNotNotifySubscriber
- WhenAddingPropertyChangedHandler_ThenNotifiesSubscriber
- WhenAddedPropertyChangedHandlerTargetIsNotAlive_ThenDoesNotNotify
- WhenRemovingPropertyChangedHandler_ThenDoesNotNotifySubscriberAnymore
These should cover all use cases.
Consuming PropertyChangeManager-enabled objects
The fact that a given object is internally (remember requirement 1.) using this PropertyChangeManager is completely hidden from the consumer:
var source = new Foo();
source.SubscribeChanged(
x => x.Name,
foo => Console.WriteLine(foo.Name));
The first argument specifies which property you're interested in, and the second is an Action in this case for the callback when the property changes. It can of course point to a class method:
source.SubscribeChanged(
x => x.Name,
this.OnRenamed);
Optionally, if unsubscribing from the event will be needed at some point, you can just keep a reference to the returned IDisposable object from the call to SubscribeChanged:
// this could be assigned to a field, for example.
IDisposable onRenameSubscription = source.SubscribeChanged(
x => x.Name,
foo => Console.WriteLine(foo.Name));
// at some later point (i.e. IDisposable.Dispose implementation of the consumer)
onRenameSubscription.Dispose();
// now the subscription is removed, even if I didn't keep the lambda around!
The source object can still implement INotifyPropertyChanged, but you may want to do so explicitly just for its support for databinding infrastructure. The consumer would still be able to cast the object to INotifyPropertyChanged if he wanted to use the "unsafe" property name strings ;). The implementation can still be made public, though.
Implementing INotifyPropertyChanged with PropertyChangeManager
The implementer defines a private field to hold a reference the manager:
public class Foo : INotifyPropertyChanged
{
private PropertyChangeManager propertyChanges;
private string name;
private int value;
public Foo()
{
this.propertyChanges = new PropertyChangeManager(this);
}
Note that the manager is generic and receives the type of the "change event source", in this case Foo.
Next, your properties need to be turned into "old-style" .NET properties with a backing field, because you need to add a call to the manager in the property setter:
public string Name
{
get { return name; }
set { name = value; this.propertyChanges.NotifyChanged(x => x.Name); }
}
Note that the call to the manager also leverages lambdas to avoid using strings.
In order to provide a custom implementation of the INotifyPropertyChanged.PropertyChanged event, you need to implement the interface explicitly and pass-through the implementation to the manager:
public PropertyChangedEventHandler PropertyChanged
{
add { this.propertyChanges.AddHandler(value); }
remove { this.propertyChanges.RemoveHandler(value); }
}
This is a restriction in the language, which prevents this event from being public. But it's not as bad as it sounds, as you want to encourage adoption of safer lambda-version subscription, which is the last bit to implement:
public IDisposable SubscribeChanged(Expression> propertyExpression, Action callbackAction)
{
return this.propertyChanges.SubscribeChanged(propertyExpression, callbackAction);
}
How PropertyChangeManager works
The manager works by dismembering the received delegates into their actual target and method info, to be able to weakly reference the former, while remaining able to call the latter. It's a plain list internally, which is scavenged every time an action is performed in the manager (this could be optimized somehow to only happen on Notify, but it simplified the implementation a bit, and it's not like property change performance is a big issue in UIs anyway).
Here's the full source.
Some tooling such as a custom tool, item template, or code snippets would be nice, I'll try to provide those in the future.
Enjoy!
You surely have set the startup application for a project countless times:
But that setting goes your user options file, the rest of the team doesn't get to reuse the setting. And what if you repave your machine or start working on a new virtual machine and just got the sources from source control? You have to re-set this value again and again.
Turns out that this setting goes to a file named after your project file plus the ".user" extension. This file is just a fragment of an MSBuild file, and would look something like:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<StartAction>Program</StartAction>
<StartProgram>C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe</StartProgram>
<StartArguments>/rootSuffix Exp</StartArguments>
</PropertyGroup>
</Project>
And because this just plain MSBuild properties, you can copy the entire PropertyGroup to your main project file, delete this .user, and check-in your change. From now on, everyone on the team will have this setting enabled, and you will have it too if you get a clean environment eventually :)
- Get the .NET 4.0 Beta 2 download from MSDN.
- Open the downloaded .exe with 7zip (i.e. right-click on file, select 7-Zip > Open Archive)
- Navigate to the .rsrc\RCDATA\ "folder" and open the CABINET file:
- Extract the contained MSI, install and enjoy!
I thought I'd need to crack the MSI open with the good old Orca tool, but turns out I didn't have to!
Stay tuned, my Reactive Framework Extensions Generator will be soon updated to RC too :)
Enjoy!
First go get the tool. It's free and it rocks.
Next, save this XML to a file with a .vssettings extension:
<UserSettings>
<ApplicationIdentity version="10.0"/>
<Category name="Source Control_TeamFoundation" Category="{2A718788-A6D9-44C5-90EF-438BF5B06A74}" Package="{4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}" RegisteredName="Source Control_TeamFoundation" PackageName="Microsoft.VisualStudio.TeamFoundation.VersionControl.HatPackage, Microsoft.VisualStudio.TeamFoundation.VersionControl, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<PropertyValue name="UserTool1" extension=".*" operation="Compare" command="C:\Program Files (x86)\SourceGear\DiffMerge\DiffMerge.exe" arguments="/title1=%6 /title2=%7 %1 %2"/>
<PropertyValue name="UserTool2" extension=".*" operation="Merge" command="C:\Program Files (x86)\SourceGear\DiffMerge\DiffMerge.exe" arguments="/title1=%6 /title2=%8 /title3=%7 /result=%4 %1 %3 %2"/>
</Category>
</UserSettings>
Finally, go to Tools > Import and Export Settings in VS and import that file by clicking Browse on the third and final page.
What this does is set the great SourceGear DiffMerge tool as the diff and merge tool to use for all your files. I find it much more usable and smart than the built-in TFS one.
For the ultimate collection of settings for diff/merge tools in VS, see James' blog post.
Enjoy.
Scott Bellware has an interesting series of posts where he discusses how to get back to productive development teams. As usual in his writing (IMO), in a rather verbose way he brings up quite a few good points. Please go ahead and read them. He links from the first entry to the next so you can follow the flow.
I agree with the analysis that unnatural organizational structures kill productivity, motivation and leadership. And I believe this is one of the reasons why even big companies turn to so-called "boutique development shops" (shameless plug there): by being small and very cohesive, these shops offer creativity and productivity levels that "mere big" ISVs can only dream of.
And it's not always only a matter of design principles, I'd add. Sometimes you need a specific area of expertise which you're better off outsourcing (i.e. Visual Studio extensibility, hardcore WCF, framework/runtime libraries, WPF/Silverlight/Blend UEX, etc.). Small shops of highly specialized professionals can save you tons of money and time. But your own dev team will certainly benefit from applying sound design principles for what matters most to your business: the business rules and logic.
Say you have a (typically autogenerated) class with properties like:
public partial class Project : IExtensibleDataObject
{
public System.Runtime.Serialization.ExtensionDataObject ExtensionData
{
get
{
return this.extensionDataField;
}
set
{
this.extensionDataField = value;
}
}
Now you can fire up the Find & Replace dialog in VS and enter the following "simple" expression in Find What:
\n:b*\{[:b\n]*get[:b\n]*\{[.:b\n]*.*[.:b\n]*\}[.:b\n]*set[:b\n]*\{[.:b\n]*.*[.:b\n]*\}[.:b\n]*\}
And use the following expression for the replace:
{ get; set; }
Don't forget to set the Use: Regular expressions option.
Running it will get you automatic properties for the entire file (or files):
public partial class Project : IExtensibleDataObject
{
public System.Runtime.Serialization.ExtensionDataObject ExtensionData { get; set; }
[System.Runtime.Serialization.DataMemberAttribute()]
public int AffiliateId { get; set; }
[System.Runtime.Serialization.DataMemberAttribute()]
public Galleries.Domain.Model.Category[] Categories { get; set; }
Yeah, I know, that expression looks like crap ;)
You know how annoying the GAC shell extension makes it to access the actual assemblies:
Utterly useless.
Of course, you surely know that you can get to those elusive assemblies via the command-line and side-step the shell extension:
But, now you need to go to each assembly folder, then its version, and so the actual assemblies are scattered through various locations.
This one-liner powershell command will get them all out in a folder of your choosing for easy Reflector-ing (create the target before running it):
Get-ChildItem C:\Windows\assembly\GAC_MSIL -filter *.dll -recurse | Copy-Item -destination C:\GAC
Windows Media Center (WMC) is based on a relatively simple (albeit awfully implemented) principle: you have ONE "server" PC holding and running your media, and then you associate any number of Media Center Extenders to it that are typically (except for the XBox 360) single-purpose devices that can only act as such and are fancy and silent enough to deserve a place in your living room.
I guess back in 2005, the entire model and most of Microsoft design decisions on this product may have be justifiable. 5 years later, none of them make any sense and IMO mean that WMC is currently a totally flawed, doomed and generally useless product for most common needs.
Why it (kind of) made sense back then
- Hardware: In 2005, you wouldn't dare subject your family to the noise, ugliness, quirkiness, uex, power comsumption, and cost of a full-blown "Home Theater PC" (HTPC) or an XBox power sucker. The Media Center Extender model made sense because you couldn't buy a full PC that was silent and nice-looking enough for the price of an extender. (but the extenders weren't without limitations either, a good review of it at the time at the supersite)
- The user experience is quite cool (but the extenders' lower processing profile meant their UI rendering capabilities were significantly worse)
Why it doesn't make sense anymore
- Hardware: nowadays you can buy a full blown PC, small, silent and power-efficient for $199-$249. Why would you want a crippled, single-purpose device when you can have the full power of a desktop, with the capability to play back any weird format you can possibly throw at it, provided you just install the right codec. No more hardware limitations and being stuck with an obsolete device.
- Software: back then, the Media Center team invented their own markup language to accommodate disparate rendering capabilities between a full PC, the XBox and a crippled extender. Nowadays we have WPF and Silverlight, no need to learn a new UI markup language. The extenders UI is sluggish at best, compared with what's possible in a PC with WPF/Silverlight.
- OS: Windows 7 is a kick-ass operating system, with a ton of features. It's a snappy, sleek, touch-friendly, smart connected (i.e. "Play To"/DLNA, HomeGroup, etc. etc.) platform. And it runs great on the smallest chips out there (it gave new life an 'old' Dell Mini 9 I had, for example).
- Home Server: having all your media in a "plain" PC is risky. You need to take care of backups, redundancy, fault-tolerance, etc. Today, it's a no-brainer to buy a Windows Home Server and let it manage all this for you, automatically, transparently, and just dead easily.
This combination makes desktop media management software a viable alternative and can certainly power your living room and projector. I believe we're at the beginning of a revolution in smart homes and connected media, just because of this new synergy and convergence.
If I had to start a project like that right now, I'd make it so that:
- It runs full WPF on the HTPCs connected to every TV.
- It supports a centralized repository for the entire house (which could be a regular PC or a Windows Home Server-WHS)
- It has a built-in extensibility model based on some dependency injection technology (i.e. MEF), and *everything* including the core functionality is a plugin
- It leverages WHS to provide mostly the same UI over the internet by leveraging Silverlight (single programming model for both), so that I can access all the same content from everywhere, and automatically takes advantage of Smooth Streaming for videos.
- It integrates with home security cameras and provides those both in the home (i.e. monitor the baby upstairs on a PiP window) or via the web (i.e. watch my home while on vacations) leveraging Live Smooth Streaming.
- It empowers a huge plugin community that can create cool advanced features like face detection on photos and videos and security recordings, provide filtered views of those, map pictures with geocoding, provide a "home connection point" where a GPS could submit road trip info, etc. etc.
For now, I got my Dell Zino HD (shipping soon) and I'm looking forward to selling the assorted Frankenstein media setup I have right now.
The future looks bright for the smart home :)
. without paying for a TypeMock Isolator license to do it ;-)
There's going to be no magic here. You have to explicitly design for testability. That's one of the things I like about mocking: if you can mock a dependency, then it means your design is loosely coupled (e.g. not tied to a particular implementation of that dependency), and you're not "cheating or taking any shortcuts. If a test can replace a dependency at test-time, your'll surely be able to replace the real implementation with something different when/if time comes to do so.
Extension methods are tricky because they are static methods, really just syntactic sugar for a "good" old static class with static methods (typically a "helper" of some sort. But what is special about them, is that they show up (provided you have the right usings/imports) in the target type API as if they were its own instance methods. This is significant, because it also means that it's very easy to pollute the target type API as you (and other referenced libraries) keep piling up these methods on it.
I therefore prefer an approach where you group your extensions under a single API, and access that API via a single extension method on the target type that becomes the entry point to your extensions. For example, say you have an IPerson interface, and you want to add secutity-related helper methods that you can use consistently from other logic or services. One way of adding a GetPermissions security helper extension method (that will get the rights of the user over a given resource, for example), would be to plug it right into IPerson as an extension method:
[Flags]
public enum Permissions
{
Read = 0,
Modify = 1,
Delete = 2,
FullControl = Read | Modify | Delete
}
public static class SecurityExtensions
{
public static Permissions GetPermissions(this IPerson person, Uri resource)
{
// get permissions for the given resource from somewhere
}
}
This would get you the API right on the IPerson object:
If you go overboard with this "extension in the root" approach, you might end up with an ugly looking assorted collection of helpers attached to the main class, such as what happened to the UML APIs in Visual Studio 2010. Look at the before and after we reference and import the assembly containing the extensions to IClass (the interface that represents a class in a UML Logical Class Diagram):
After referencing Microsoft.VisualStudio.Uml.Extensions.dll and adding the corresponding using/import:
(I pasted together four pages of intellisense for added effect, but you see the point, rigth?)
Extension Interfaces
Another alternative is to group extension methods that provide related functionality under what I'd extension interfaces. In our person example, we might find out that the security-related methods start growing, and we'd like to keep the main API clean, so we introduce the ISecurity extension interface, and provide an extension method that is the entry point to it:
public interface ISecurity
{
Permissions GetPermissions(Uri resource);
}
public static class SecurityExtensions
{
public static ISecurity Security(this IPerson person)
{
throw new NotImplementedException();
}
}
Now, the consumer of the IPerson object can see that there is security-related behavior available to him, but won't see what those are unless he needs to:
Typically, the SecurityExtensions class will instantiate a non-public implementation of ISecurity that does the real work, passing the person to work on as a constructor argument:
internal class Security : ISecurity
{
private IPerson person;
public Security(IPerson person)
{
this.person = person;
}
public Permissions GetPermissions(Uri resource)
{
// get the real permissions for the person
// field we have received, for the given resource
throw new NotImplementedException();
}
}
public static class SecurityExtensions
{
public static ISecurity Security(this IPerson person)
{
return new Security(person);
}
}
The attentive reader might have noticed that, being a regular interface, the extension interface now can expose properties where it makes sense, overcoming the lack of support for extension properties in C#. For example we could add a Roles property quite easily:
And because the extension interface is nothing more than a fluent interface in the end, you can use the trick I blogged about before to hide those pesky System.Object members:
How to mock extension methods, again?
Back to the testing subject, in order to test the Update method above, we'll need to replace the ISecurity implementation, right? Because we followed the extension interface design approach, we now have a single extension method to replace, the one that creates the default implementation of the ISecurity inteface. And if you look at that method, all it is being a factory for creating an implementation of ISecurity given an IPerson:
public static class SecurityExtensions
{
public static ISecurity Security(this IPerson person)
{
return new Security(person);
}
}
So for testing purposes we can just add an internal factory that will isolate the extension method behavior, and that we'll replace for testing purposes:
public static class SecurityExtensions
{
internal static Func<IPerson, ISecurity> SecurityFactory = person => new Security(person);
public static ISecurity Security(this IPerson person)
{
return SecurityFactory(person);
}
}
The test for the Update method above, which will have internals visibility enabled from the project under test, will simply replace the factory with one that returns a mock:
public void WhenPersonHasNoModifyPermission_ThenThrowsSecurityException()
{
var security = new Mock<ISecurity>();
security.Setup(x => x.GetPermissions(It.IsAny<Uri>())).Returns(Permissions.Read);
SecurityExtensions.SecurityFactory = person => security.Object;
var controller = new DocumentsController();
Assert.Throws<SecurityException>(() =>
controller.Update(new Mock<IPerson>().Object, new Uri("http://foo")));
}
And voila! We have just passed a test where the class under test uses an extension method:
public class DocumentsController
{
public void Update(IPerson person, Uri document)
{
if (!person.Security().GetPermissions(document).HasFlag(Permissions.Modify))
throw new SecurityException();
// ...
Also note that the intenal Security class that implements ISecurity can also be fully tested in isolation.
Happy moqing!
PS: remember the focus of this post is on mocking extension methods, not on how to design security for your domain ;-). Feel free to mentally replace ISecurity with IFoo, GetPermissions with DoSomething, etc., as needed.
If you are doing Visual Studio extensibility (VSX) work, you are probably aware of the existence of the Visual Studio "Experimental" instance. This is basically an instance of VS that has its own isolated registry, settings, extensions, etc. This allows you to test your extensions to VS without polluting your main development environment.
Sometimes, the environment might get corrupted for whatever reason, or it might be that you just want to test your extension with a clean environment after messing with it for a while.
The Visual Studio SDK does come with a tool to reset the experimental instance, available from your Start menu with the name "Reset the Microsoft Visual Studio 2010 Experimental instance". That will not, however, give you the pristine environment you got the first time you start the experimental instance to test your first extension.
In order to get a super-clean environment, here's what you need to do:
- Close any running instance of VS Experimental.
- Delete the entire folder %LocalAppData%\Microsoft\VisualStudio\10.0Exp
- Run regedit.exe
- Delete the registry key HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0Exp
- Delete the registry key HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0Exp_Config
- Run the command "Reset the Microsoft Visual Studio 2010 Experimental instance" from your start menu.
Now you'll have a fully restored environment. Also, any existing extensions you have in your main environment will be copied over to the experimental instance, with one caveat: you'll have to manually enable them from the Extension Manager UI from a running experimental instance to get them running.
If you've been doing VSX work in previous versions of VS, you'll sure appreciate the drastically simplified install/reset experience enabled by the new deployment mechanism in VS2010 via Extension Manager and VSIX files. If you have not, then this doesn't sound so scary anymore, does it? ;-)
Happy extending!
You probably know already that the Reactive Framework Extensions (Rx) is a new library on top of .NET 4.0 and Silverlight that allows developers to leverage the expressiveness and power of LINQ for .NET events. It brings an entirely new paradigm for doing event-driven apps, and therefore shines in WPF/Silverlight scenarios.
Read more about Rx at the team blog, the project home page and Matthew excelent blog series.
Even with the general availability of the bits for VS2010 beta2 at DevLabs, there's still quite a bit of work you need to do in order to leverage the extensions. Specifically, you need to turn your events into IObservables that can then use the Rx extensions for querying and subscribing. This is a lot of repetitive and boring code that can be easily automated.
That's precisely what this Clarius Labs provided extension does, enabling Reactive Framework Extensions for arbitrary assemblies, without writing any code. It basically traverses all public types in a given assembly (i.e. PresentationFramework.dll, for WPF) and generates a "Reactive" assembly for it (i.e. PresentationFramework.Reactive.dll) which contains the necessary extension methods for all public types that expose generic or custom delegate events that can be automatically converted to IObservables. With that in place, you can simply use the Reactive() extension method on your classes and access in a strong-typed fashion all events of that type as IObservables:

In order to get the extensions assembly generated, you simply right-click on a project or assembly reference, and select "Create Reactive Extensions":

and a new assembly will be generated and referenced automatically:

which will enable you to use LINQ operators and the new Observable APIs for all events exposed on all public types for the given assembly.
Matthew sample using our generator looks like:
var mouseMoves = from mm in mainCanvas.Reactive().MouseMove
let location = mm.EventArgs.GetPosition(mainCanvas)
select new { location.X, location.Y };
var mouseDiffs = mouseMoves
.Skip(1)
.Zip(mouseMoves, (l, r) => new { X1 = l.X, Y1 = l.Y, X2 = r.X, Y2 = r.Y });
var mouseDrag = from _ in mainCanvas.Reactive().MouseLeftButtonDown
from md in mouseDiffs.Until(
mainCanvas.Reactive().MouseLeftButtonUp)
select md;
Go to the Visual Studio Gallery and give it a try!
1 ...