Category: Development


Ever since I completed my (mandatory) 9 month military service on the 4 of November 2010, I was planning on creating a game that would mock it a little. I was aiming for a simple Tower Defence game and my platform of choice was Silverlight.

Only, there were two problems. First, I was busy at the time; there was no time (or mood) for side projects. Second, I had no experience with Silverlight at the time. Had I proceeded, there would be a third problem, the fact that Silverlight never enjoyed any real recognition and then it was repurprosed for the Windows Phone Platform. Plus, I’ve never worked with Flash (which would be the logical choice) so not only I’d have to spend time learning it, it would also cost me quite a bunch.

 

Fast forward one year and a half later. The other day, I came across this: http://www.cuttherope.ie/ which is a port of the famous Cut the Rope game to Javascript and HTML5 canvas. Well well well, look at that. Excellent framerate, nice UX and good compatibility (IE, Firefox, Chrome and Opera – no Safari though).

Seeing this, I’ve decided to have another look at my game idea (yeah, I still haven’t learned Flash, nor I have the money to buy it). While I am not new to the concept of 2D game creation and its requirements (I made a simple platformer 10-15 years ago in DOS) I had completely no idea about working with the Canvas element.

Looking around the internet, I found a rather comprehensive list of JS game engines, all with different levels of features, complexity, licensing and documentation. Thing is, I did encounter a few problems with almost every engine out there. Since the type of the game I was planning was a Tower Defence game, most of the baggage that comes with these libraries is not really useful for such a game. Combine this with the rather primitive documentation on most libraries, the learning curve is very gradual (that’s bad).

Here are some game engines that I found particularly interesting:

  1. Game.js This is an example of a small & solid engine which has rather tight coupling. It’s worth looking at, but you can also have a look at…
  2. Crafty has an interesting feature, in that it’s component based. Adding features (such as collision detection, movement etc) is as simple as attaching a component to it. It works very nice, but the documentation/tutorials are a bit anemic, plus it doesn’t support layers which I kinda like to have.
  3. The Render Engine is a monster of a game engine. However, due to its complexity and the lack of proper documentation and tutorials I find it kinda hard to get into. I will definitely keep an eye on this one.
  4. Melon.Js is a game engine that’s almost exclusively designed for platform games. Plus it has some nifty features, such as that you can design a whole level using an external editor (Tile) plus that it supports viewport scrolling out of the box. Since I’m planning on creating a platformer for my next game, I’m seriously considering using this one.

In the end, I decided to do it on my own and start from scratch. Well, not completely that is. I came across Kinetic.JS which offers some few but useful features. Specifically, not only it supports layers, but it’s designed to work with double buffering under the hood (which drastically increases performance). It also handles the drawing of objects for you.

 

So far, I created a Sprite class that subclasses the Shape class of Kinetic.js that represents a… shape object with which you can interact. I added some basic sprite map & graphical state support and it works ok so far. I’ve tested rendering 210 32×48 sprites with 4 levels of animation each in a 800×480 window with no performance issues (with the exception of Firefox which has an issue with mouseover – I have to look deeper into it). As soon as I make progress with the game, I’ll post again.

 

I am far from an expert with Javascript and I’m sure that the end result could be improved. In any case, when the game is posted I will post it under a MIT license with sufficient documentation.

“Properties are bad and should not be allowed in Java”

Wow… Once again, I’m impressed. The above is from a comment in this blog post. I remember admiring java for what it offered back then: innovation, garbage collection to the masses, clean APIs etc. More than 10 years have passed since my initial impression, and I can safely say now that this admiration has turned into despisement.

 

I’ve never denied that I am a .net fan, perhaps because it proved to be so much better than Java when it came out, containing (most of) the right parts from C/C++ while neatly offering what Java did and more. Not only that, but each version of .net and C# (my primary language of choice in the platform) offered an enormous amount of innovation.

It’s a fact that when .net came out, nobody cared much, apart from the Microsoft crowd. Everybody was talking about how Microsoft copied Sun’s invention and how C#/.net was a rip-off of Java. 10 years later, the .net platform is so ahead of the Java one, one can recognize patterns of Sun (and now Oracle) closely copying some of .net’s developments back to Java. That’s of course limited to stuff like Enums, Attributes (called Annotations), strings in switch statements and so, nothing really advanced (such as say, LINQ or DLR).

[more]

But, enough with the Java bashing. I don’t want to focus on that (for various reasons) and I only mentioned it so that I can pinpoint the blame. So, who’s to blame? The Luddites of the Java community that seem to hold innovation.

To be honest, I’m using .net as much as I can. I love it. I am not a fanboy, but I really enjoy working with it. Even when I’m forced to use other platforms, such as good-ole C++, PHP, Java, etc, I will first check whether a .net solution is feasible.

No matter what my preferences are, I still don’t want to see platforms I work with wain and become irrelevant. I want Java to become a modern language, I want it to copy the functional innovations C# brought to an imperative world. I want it to have proper generics. I want to have properties that simplify the development without sacrificing verifiability. I don’t want it to disappear; that would only make the fanboys happy (and really, who gives a damn about them anyway).

All in all, I want the Luddites to shut the hell up and to see Oracle ruling the Java world with an Iron Fist ™. Well, that sounded wrong. I mean an Iron Fist on the Java architecture teams, much like Microsoft does. Hate it as much as you want, but what allowed C# and .net to become modern and slick, were the genius minds of its creators and not the subgenius whiny little bitches that, while have no idea on how to properly design, support, extend and use a platform, actually demand that all innovation should cease. Just to be clear, I include myself in the subgenius crowd (just not on the whiny bitch one). I am smart enough to know that I am not smart enough to create a high performant language & platform and as such, I want the people who’ll actually do the work to be smarter than I am, so that I can get back to creating web-sites and crappy business applications we all hate (but also love to design and plumb together).

You give me new features? Great, I’ll sit down and learn about them and try to make the best of them, not whine about “how they killed the simplicity of my language”. This is what I think of the Java Luddite part of the community.

Hey, would you guys like some shiny new operator overloading? “Nooooo, it confuses and infuriates us; we don’t read component documentation anyways so we have to make sure that everything is dumbed down as much as possible, even if we have to do stuff like a.add(b.multiply(c).subtract(d)) where  a+(b*c-d) would suffice”.

This goes on and on for about EVERY damn feature that’s to be introduced in the language. What about Properties? “Nooo, they are bad and should not be introduced. So says me, the anonymous internet commenter”.

Okay, but Closures sure sound nice and useful, right? “Ummm, I don’t know, they look scary. What’s wrong with writing a few extra 100 lines of code here and there?”

 

I can go on and on but in the end you will find that, in most questions like the ones above the answer is “X is considered harmful for the Java language”. It’s nearly impossible to teach new paradigms to these people, but apparently their voice is loud enough to keep java from becoming a truly modern language. Sorry, it’s not modern anymore, deal with it.

In the end, the solution is to release Java v2.0 which will do away with the stupid limitations Java 1.x has and will build on a more flexible model, with time saving features from other languages and correct implementations that were broken before (such as generics). For f***’s sake, copy Microsoft, Python and Ruby  on that – you won’t have to feel shame for it.

You also don’t (and shouldn’t) have to make it fully backwards compatible – you can develop the two major versions in parallel for a while, releasing perhaps 1 or 2 more 1.x versions. That, together with an Iron Fist ruled team of Architects who can actually judge whether the voice of the community on a matter has merit or is simply a projection of the fear incompetent developers have (tm), is the only way to make Java relevant again.

 

I honestly look forward to it.

Recently, I was forced to look into PHP caching, thanks to a series of events. Here’s what happened:

Once upon a fine day, the (windows) server demanded that I will install some windows updates it found and I proceeded in complying with my master’s wishes (dare say no, and it will kill your customers’ sites. It already send me their fingers once). After the restart though, I noticed that all of our PHP sites were timing out. It didn’t take long to find out that the one to blame was MySQL which due to the massive amount of files in the temporary folder, apparently needed a very long time to create its temp files. In the end, I found out the cause and boy, was it ugly or what?

It seemed PHP was creating session files on the Windows’ temporary folder but wouldn’t delete them after the session had expired. As a result, the amount of files in the folder reached the 1.000.000 (!), all of which were 0 or 32KB long, but nevertheless enough to make anything that tried to access the folder crawl like it never crawled before (such as MySQL).

[more]

This ugly event mustn’t  have to happen again and I need to ensure that. So, I took a deep breath and began digging into php.ini. It seemed that the following piece of advice was giving me a hint:

; If you are using the subdirectory option for storing session files
; (see session.save_path above), then garbage collection does *not*
; happen automatically. You will need to do your own garbage
; collection through a shell script, cron entry, or some other method.

Still, that wouldn’t explain why such an option was set, since I neved touched the session section of the php.ini, ever. I refuse to believe that by default php is designed to kill its hosting server (I may be wrong though, feel free to correct me). I took a quick look into the caching option I actually used, which was provided by the session.save_handler setting, which was set to files. Searching around for different options I could try, I found out about WinCache.

 

WinCache, or Windows Cache Extension for PHP is PHP accelerator in the form of a PHP extension which is designed to work in Windows, but strangely enough, not limited to IIS (although being developed by Microsoft). WinCache though is not just an opcode cache but also offers some other nifty features, such as file caching, user data storage (more on that later) and session storage. Also, tests conducted by other people seem to indicate that it does a pretty great job, even when compared to other solutions. Plus, it won’t mind if you’re having 1 or 16 PHP FastCGI processes, since the cache it creates is centralised, thus avoiding data duplication!

Now go to RuslanY’s (WinCache’s creator) blog and thank him for his great work!

I have to admit though that initially, I was sceptical about WinCache. I had tried WinCache as a beta and it had some serious bugs which made some of our PHP sites to unexpectedly crash and as such, I had removed it completely. Not so with version 1.2.614, a development release that gave me no problem. After verifying that all of our PHP sites would work without issue when this extension was enabled, I was curious to find out more about its session handling option. So, I changed PHP’s temporary folder to one that would be untainted by other processes, changed the session.save_handler option to wincache and went on an angry rampage using openload, which hammered my servers with requests, the best part of which was that it would create a plethora of new sesions. Let me tell you, I was relieved to see that WinCache only creates a single file for handling PHP’s sessions.

 

So, I had certainly solved that annoying problem, but now WinCache had proven to be interesting and had to find out more about it. After all, I was sold on this nice live stats page that showed the status of WinCache. The best part was already set and forget. Opcode caching and File caching were applied automatically to all of our PHP applications and required no tweaking from my part. The same goes for session caching (although in this picture the hit/miss ratio is low due to using openload which creates lots of new sessions). What peaked my interest was the User Cache session which initially was 0. I found out eventually that user cache is nothing more than an object storage provided by WinCache and which is accessible using the WinCache provided functions.

“Big deal” I thought. “We’re talking about PHP on Windows, who would bother to lock-in its application to Windows and WinCache?”. Although the question is valid, the answer was far simpler: “Caching plugins!” Indeed, applications that up until now used the disk to act as a cache, could benefit greatly from WinCache if they used it instead for that same purpose. First case in point? WordPress, a platform which is favoured by many of our clients.

 

Let’s take a specific example, extrahype.com. Extrahype is a heavily modified site based on WordPress for all things geek, be it movies, games, pop culture and more and we’re lucky enough to be hosting it. Using my crude benchmark tool, openload, like a an angry caveman wielding an obsidian knife, I went and performed a simple benchmark of its start page, without using WinCache or any form of caching within the site itself. The results on the 2xDual Opteron 2212 were a bit disappointing, even though this was PHP on IIS on a not that fast server processor. I only got about 14 requests/second, which is low. In contrast, our in-house developed site rekonit.com an online review aggregator for stuff that matter (such as cars, movies and games, you know, the geek stuff you see on extrahype.com) which uses ASP.net 4.0 & MSSQL server and self designed caching algorithms gets about 350 rps. Note, we are currently redeveloping rekonit.com in ASP.net MVC 3 & MSSQL, so get ready to be amazed within the summer (yes, it will also look cooler).

I then proceeded and enabled WinCache in the php.ini. The results were very positive. With WinCache enabled, the average requests/second extrahype.com could handle rose to 31 rps, a difference of more than 2 times! That was good, but still not good enough.

Here’s where WinCache’s user cache came into play in the form of WordPress plugin, WinCache object cache. After I installed this, I could see the user cache section in the WinCache statistics page populated with data. Did it make any difference? Well, a minimal one. The average rps climbed from 31 to 34 rps.

The differences were reasonable and it’s obvious here that the bottleneck appears to be the database server. Still, it provided my PHP websites with a nice performance boost that only costs a little RAM (thankfully, that’s in abudance).

 

I then proceeded on testing it with PHPBB 3. Using the same method of “before and after WinCache” I would end up with 18 and 30 rps respectively. PHPBB 3 uses a file caching mechanism as its default. I found an experimental WinCache implementation which, usurprisingly, uses WinCache’s user cache. The difference was still minimal, this time from 30 to 33 fps, but still a no brainer compared to other forms of caching. Note that the problem here were the serialized database accesses, since the PHP FastCGI processes were are at a cosy 10% of CPU usage while MySQL was struggling around 25-30% (a whole core in a quad core system, plus a little more).
As a comparison, a PHPBB 3 installation on my development machine (an Intel Q9550 quad core) achieves about 59 rps without WinCache and 82 rps with it enabled, with the same database bottleneck issues.

 

In the end, WinCache (as other PHP accelerators do) offers an almost free performance upgrade to your PHP applications. Its extra features such as file, user and session caching & handling are indispensible even if you don’t have that much RAM to spare. It’s highly recommended and if you run PHP on Windows you should definitely check it out!

Comments? Criticism? Testimonies? Feel free to comment below!

 

PS. Before closing this article, I’d like to present you with two additional plugins for WordPress that managed to blow my mind with their results:

I’ve also tested W3 total cache for WordPress, a highly sophisticated caching system which is designed to take advantage of any caching option you can think of, such as opcode and file caching, page minifying even CDNs and some additional features that didn’t have the change to use (yet). The improvement is simply spectacular, since with it enabled plus setting it to take advantage of winCache’s features (and WinCache obviously active) the requests/second I achieved for extrahype.com exceeded the 300 rps mark! This result is achieved mostly by creating static versions of components whenever it can.

If your site however does not need a complex caching mechanism nor is very complex in nature (extrahype.com for example is not as complex as it might seem) you can opt for another caching plugin, simply named Quick Cache. Quick Cache is essentially a very simple caching plugin that creates static versions of your site’s pages. It doesn’t have the sophistication level W3TC has and only few differentiation methods of the page are recognised, but if your site’s user base consists mostly of unregistered visitors or you want to deal with a sudden Reddit/Digg/SU/Slashdot attack, it will do a magnificent job. How magnificent? Well, with Quick Cache enabled in extrahype and WinCache enabled in the server, I managed to get 610 rps! This amazing number is due to the web server only serving static content, with minimal PHP processing.

Since most of our WordPress clients don’t really need (yet) the sophisticated features of W3TC and they mostly have unregistered users, we’ve decided to enable Quick Cache and migrate to W3TC when required. No matter what you select though, make sure the plugins have the required permissions on the cache folders they create, or you may end up with a bazillion of cache files!

I’ve started messing around with custom websites based on WordPress lately, since it offers a very flexible platform with lots of functionality while still allowing you to customize the final result to your heart’s content. Really, the only real issues with this approach is that 1) we are talking about PHP which happens to not be my platform of choice (but I can swallow my pride and develop on it anyway) and 2) WordPress’s performance issues that can be easily solved with a caching plugin.

 

So, I’ve created a nice custom layout from scratch. Tested it on all major browsers on which it worked perfectly (except from IE 6 and 7, but I can ignore these at this stage). Then I went on to implement specific functionality from WordPress on the layout. The drill is quite simple. You seperate the HTML into template files. In this case I had created 3 of them, header.php with the doctype, head tag and header declaration, footer.php with the site’s footer and all closing tags, and index.php with the main content of the page. You render the header by using WordPress’s get_header() method and get_footer() for the footer.

After a while, I’d noticed that viewing the page on Firefox there was some kind of a blank white space border in the uppermost side of the page, which had no reason to be there. I excluded the beta nature of the browser as a probable cause, since the standalone layout worked perfectly. Then, I attempted to view the result on IE and… there are no words to describe the colossal mess the browser rendered. Oh yes, the white border was there too.

As if that weren’t enough, double clicking on that white space on Firefox and then viewing the “selection source” would produce a quite different html source, specifically moving all declarations that belong to a <head> tag into the <body> tag. Chaos, chaos I tells ya!

Then, I moved the contents of header.php back to index.php and removed the call to the get_header() method. Whadayaknow, it worked perfectly again. Feeling adventurous, I added the call to the get_header() method again in the index.php file but with the header file empty. Oh boy, chaos once again.

 

I was stumped. There was no logical explanation for that (as far as I could see), since the source produced was the same in each case. But when I checked the file sizes and found them different, I suddenly knew… It was the 3 characters known as Byte Order Mark, and should be the first thing that should appear on a Unicode document, be it a text file, a code file or a Word document. It’s a sort of metadata, only that it’s contained within the document contents themselves. It’s quite useful actually since not only it informs you about the endianness of the document’s encoding but of the unicode encoding variant used. Most applications that are Unicode aware usually remove those characters when they present or process such data, but there are few that do not and… well… the least painful result is the literal appearance of these characters on the document itself. In other cases, such as in PHP this means misrendered documents due to them app.

The easiest solution is to save the files without a BOM, especially the one containing the DOCTYPE declaration! There’s also supposed to be a zend configuration option (enable-zend-multibyte) that checks for the existence of the BOM, but from what I can gather it’s quite buggy. Also, the folks at PHP expect such issues to go away with PHP 6.0 (and here’s another reason why I like developing on the .net platform so much: I don’t have to deal with such trivial issues).

 

 

In any case, that’s 2 hours of my life wasted on one of the most idiotic issues I’ve ever encountered…

In the old days, when arguments like DataSets versus Objects still mattered and ORMs were unknown to the majority, I held a firm position on working with objects rather than raw database data, regardless the size of the application.

Things have changed now, and objects dominate almost every application. In the .net world, with tools like LINQ to <everything> and whole bunch of different ORMs, using raw database data seems redundant and possibly dangerous since it is less easier to enforce business and validation rules.

 

One thing that always bugged me though is to find ways to minimize wasted memory due to unecessary copies of objects (especially when serialization takes place between layer boundaries), minimize the chances memory leaks (leaked events anyone?), etc.

Image a Product object. Let’s say that this object contains a reference of a User that registered it, a collection of Users that bought it , a collection of Products that are related to it, a collection of Comments (which in turn contain references of Users that authored each comment) and the list goes on and on. You can see that the nesting can go quite deep. Thankfully, when all references live on the same application domain, the above nesting has no effect on the used memory.

When designing for n-tier, separated application domains must be taken under consideration, be them on the same machine or not. This is where serialization comes into play, since you need it for transporting the objects between the tiers. This means increased communications traffic (since you need to serialize pretty much the whole object graph). After the other side receives the object, those nice live references are now gone; two Product objects that refence the same User that registered, are now pointing to separate, yet same User objects.

 

You can fix most of these problems manually, but it’s boring and error prone. A practice I personally follow is to create two properties for each expensive child. For example, should we had a property RegisteredByUser of type User on the Product class, I’d create a second property named RegisteredByUserID of type int. The RegisteredByUser property would have to be read only, and retrieve the value from a repository by using the value of the RegisteredByUserID property. It would look something like that:

public int RegisteredByUserId { get; set; }
public User RegisteredByUser { get { return Repository.Find(this.RegisteredByUserId); } }

If null instances are allowed, I’d implement as in follows:

public int? RegisteredByUserId { get; set; }
public User RegisteredByUser { get { return this.RegisteredByUserId.HasValue ?
ARepository.Find(this.RegisteredByUserId.Value) : null; } }

I do this manually (I’ve found out that for most ORMs it’s a bit difficult and unelegant to have them play nice with n-tier architectures; let’s hope that Entity Framework 2.0 will improve things), but it’s not such a big deal. What this trick offers, is the ability to avoid a seek to the repository when I only need the Id of a child object, plus the reduced size of the serialized object. No child User object is serialized. Of course, a similar repository should exist on the other side, otherwise ARepository will simply throw a NullReferenceException. By only having indirect references, I am also guaranteed that no doppelgängers exist, since every reference is retrieved by the repository.

The repository that handles the above request can then load the required instance on first demand, or have it loaded preemptively. It’s also much more easier to implement cache expiration policies because, I can guarantee that a Product with an ID of 5 will be the same in every object that holds a reference to it.

 

So, the above work pretty nicely, but… what about collections? More specifically, what about dictionaries? How can I achieve this shallow-by-repository reference on a Dictionary<int, Product>? This is where the FlexibleDictionary comes into play.

Note: FlexibleDictionary has been designed to work with the Static Autofac locator (read about and download it) for convenience. You register an implementation of the interface IFlexibleRetrievable<Tkey, TValue> which contains a method Find(TKey key) which returns an instance of type TValue. This is used for automatic resolution of the repository that an instance of FlexibleDictionary<Tkey, TValue> will use to retrieve the values, and avoid specifying it at runtime.


Internally, the dictionary is but a HashSet, and does not store any values. Suppose an instance of FlexibleDictionary<int, Product> named fd. This has been configured to a repository ProductsRepository which also implements IFlexibleRetrievable<int, Product>. When you want to add a product to fd, you must only add the Id of that product, no instance of it! Remember that since every retrieval is done by the repository and the repository itself is responsible for retrieving the values requested by it, there would be no point in adding a reference directly to fd.

Now, let’s say that you want to retrieve a product with an ID of 5 from fd (of course, you must first have added that ID 5 to the fd first; whether it already exists on the repository or not is irrelevant). FlexibleDictionary will check its internal HashSet to verify that it contains that ID 5, and then return it from the repository.

 

This gives us the same nice advantages as in the shallow properties. I can see you asking though “yeah, but what about the performance of it? Those requests and seeks surely hurt and iterations should be very slow”. I was worried about that myself (since every item is retrieved by the repository individually), so apart from the profiling on my applications, I’ve run a small benchmark involving a simple value retrieval and a Where operator. Here are the results (Q9550 quad core with lots of RAM):

Retrieving a single value, 5.000.000 times:

Normal dictionary: 0.135 seconds (0.145 without optimizations)

Flexible dictionary: 0.385 seconds (0.683 without optimizations)

Performing a Where operator in a dictionary containing 5.000.000 items:

Normal dictionary: 0.198 seconds (0.198 without optimizations)

Flexible dictionary: 0.313 seconds (0.355 without optimizations)

 

The FlexibleDictionary might be 1.5 to 3 times slower, but judging from the test volume, that’s a non issue. I would increase the test numbers, but then the Visual Studio test process would run out of memory!

 

All comments. criticism and suggestions for improvement are welcome!

FlexibleDictionary.rar (68.78 kb)

Θυμάστε τον κώδικα που παρέθεσα χθες;

 

var controllerTypes = from type in System.Reflection.Assembly.Load(WebConfigurationManager.AppSettings[ConfigElementKeys.ObjectContainerAssembly]).GetTypes()
where type.IsSubclassOf(typeof(ObjectBase))

select new { ObjectType = type, Inheriting = type.BaseType };
foreach (var type in controllerTypes) if (type.ObjectType.IsGenericType) builder.RegisterGeneric(type.ObjectType).FactoryScoped().As(type.Inheriting);
else builder.Register(type.ObjectType).FactoryScoped().As(type.Inheriting);

Όταν πάμε λοιπόν να δημιουργήσουμε ένα generic αντικείμενο, με την παρακάτω εντολή…[code:c#]AutoFacLocator.Instance.Resolve<VoteBase<ProductBase>>()[/code]το Autofac διαμαρτύρεται πως δεν μπορεί να βρει καταχώρηση για το “VoteBase<ProductBase>”. Τι είναι αυτό που προκαλεί το σφάλμα;

 

 

Η απάντηση βρίσκεται στον τρόπο που γίνεται register ένας generic τύπος, και συγκεκριμένα στην γραμμή [code:c#]builder.RegisterGeneric(type.ObjectType).FactoryScoped().As(type.Inheriting);[/code]

Κατόπιν 2 ημερών αποτυχημένης αναζήτησης, κάποιος παρατήρησε κατά το debugging ότι το type.Inheriting είχε ως FullName (System.Type.FullName) null τιμή. Αυτό μας παραξένεψε. Πώς είναι δυνατόν ένας τύπος να έχει null full name; Τι έχει να πει το msdn για αυτό; Πράγματι…

[code:html]If the current type contains generic type parameters that have not been replaced by specific types (that is, the ContainsGenericParameters property returns true), but the type is not a generic type definition (that is, the IsGenericTypeDefinition property returns false), this property returns null reference (Nothing in Visual Basic). For example, consider the classes Base and Derived in the following code.[/code]

Με άλλα λόγια, ένας open generic τύπος, έχει null FullName property σε αντίθεση με έναν closed generic (πχ. IList<string>).

Η λύση λοιπόν είναι να αλλαχτεί η εν λόγω γραμμή με την παρακάτω:[code:c#]builder.RegisterGeneric(type.ObjectType).FactoryScoped().As(type.Inheriting.GetGenericTypeDefinition());[/code]

Και πράγματι, το Autofac δημιουργεί κανονικά τα αντικείμενά μας!

Σε ένα αρκετά απλό σενάριο Inversion of Control όπου με την χρήση του Autofac φορτώνουμε δυναμικά τις concrete υλοποιήσεις μιας εφαρμογής πρόσφατα αντιμετωπίσαμε ένα περίεργο πρόβλημα όταν τα generics μπήκαν στο παιχνίδι.
View full article »

Switch to our mobile site