JSEDLAK » C#

Archive for the ‘C#’ Category

Korkboard 1.0.0.4

Korkboard Screenshot

Korkboard is a little tool I have been developing that enables a uniform method of storing multiple items on the clipboard. When Korkboard runs, it hooks into the clipboard chain and attempts to intercept messages as you use the Copy and Cut commands. It then stores the items on its own list so that they may be retrieved at a later time. It is important to note that Korkboard does not mess with the functionality of the clipboard. If you copy an item, the clipboard works as expected without any interruption or user required interception. Check it out, and let me know what you think!

Korkboard is written in WPF/.NET4 and uses ClickOnce to manage the installation and update processes.

Update: Added the Zip file for those having trouble using the ClickOnce method.

What is DMS?

During the last semester I was taking a class on ASP.NET where we formed teams to write a website from scratch. The website was a “project manager” that would help users maintain projects, employees and customers. Given my experience with ASP.NET prior to the class, my team hit the ground in a full on sprint. We hit a wall when it came time to bind the site’s controls to the data behind it, in this case a Microsoft SQL database. The problems weren’t associated with a lack of knowledge but rather the gross disconnect between interfaces and the data with which they associate. It is easy to think that a textbox on a page can represent a name, but how that name is actually filled in can be the most complicated process.

This is just one instance of running into issues with data. How many times have you used a converter of some sort to scrub data or used a validator to make sure it can be stored? How many times have you written the same try-catch block for the SqlConnection class? How many times have you written a statement with “XmlDocument” or an instance somewhere in the middle? I have come to realize that there within the .NET Framework, there are many classes to get all the work done, but they aren’t really put together in a unified way. When you look at all the data-oriented classes (e.g. System.Xml.*, System.Data.*) you will find that there is no grand picture. For some reason the framework architects didn’t take a step back and see a possibility to unify the approach to reaching, converting, validating and consuming data.

So what is DMS? In short, the Data Management System prototype is a look into how possible it is to unify the approach to using data and whether or not it can make a developer’s life easier. The first step is to consider open architectures that are highly extensible and configurable. The current version of the DMS Prototype is focusing on just that by experimenting with converting runtime objects to and from XML. The important part isn’t the conversion; XML serialization has been done to death before. The important part to take away is that the serialization is being done in an abstracted manner. It is trying to gain as much information as possible from as little information as possible. The fewer attributes a developer has to use and the more generic they are, the easier life will be.

Read the rest of this entry »

FGF: It’s All About Abstraction

One of the major themes present in the design of FGF is abstraction of functionality from its implementation. The major reason for this is because one of the major goals of FGF is to provide functionality without forcing developers into a corner. The idea is if the base of the framework is modular and open, the rest of the framework will fall into place very easily. So I begin the implementation of FGF by fixingimproving the XNA Framework’s Game class with an abstraction of its functionality. The reason for which will become apparent when the component classes are improved at a later time.

The important question to ask here is what can a game do? We can run a game, and exit a game but also add and remove components and services. Thus the IGame interface is born (within the FocusedGames.Xna project):

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using Microsoft.Xna.Framework;
 
namespace FocusedGames.Xna
{
    public interface IGame
    {
        void Run();
        void Exit();
 
        Vector2 ObjectToScreen(Vector2 objectVector);
        Vector2 ScreenToObject(Vector2 screenVector);
 
        GraphicsDeviceManager DeviceManager { get; }
 
        DisplayOrientation DisplayOrientation { get; set; }
        Vector2 DisplaySize { get; set; }
 
        bool IsLoaded { get; }
 
        float TargetFrameRate { get; set; }
 
        ModuleCollection Modules { get; }
    }
}

Read the rest of this entry »

FGF: Getting Started

This series is devoted to the design and development of my framework, FGF (Focused Games Framework), and aims to cover topics like async content management, WCF services, and many more. In this first article, I cover how to setup Visual Studio 2008 for coding the framework. It is important to understand that I will be using Visual Studio Team System 2008 and thus may have features that are not available in the Express edition. It is possible to get around many of these or ignore them completely, however, so not having Team System does not mean developing FGF is impossible.

The first step is to open up the IDE and create our solution. When starting a large solution such as the one for FGF, I find it useful to create a Blank Solution so that the solution’s name can be different than that of the first project. Again, this can be worked around in Express as well as other versions of the editor.

Blank FGF Solution

Read the rest of this entry »

Utilizing XSLT with FGF

After developing with the Sitecore CMS for a couple of months I have seen what XSLT can offer in terms of a powerful web technology. I decided early on, before using Sitecore, that Vodka 2.0 would have to support XSL transforms since the content is stored as XML. The following is a sample of how to work with XML and XSLT in the second version of the Focused Games Framework (FGF 2.0).

While the XSLT code can go pretty much anywhere in the ASP.NET pipeline, for now I have put it in my main Controller. Note that this code is not final, I will be looking into a better way to streamline the content retrieval process.

?View Code CSHARP
1
2
3
4
5
6
public class ContentController : Controller
{
    public ActionResult Get(string uri)
    {
        Content content = GetContent(uri, -1);
        Content template = GetContent(content.TemplateId, -1);

Next the XslTransformer class is instantiated and a test extension is added. Extensions can be simple or complext .NET classes. Again I plan to streamline this process and support loading from the web.config file.

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
        XslTransformer transformer = new XslTransformer(GetDocument);
        transformer.AddExtension(
            new XsltExtension
            {
                Namespace = "http://focusedgames.com/vodka",
                Provider = new VodkaXslExtensions()
            }
        );
 
        ViewData["Content"] = transformer.Transform(uri, template.Meta.Uri);
 
        return View("Get", "~/Themes/FGDN/Theme.master");
    }

When the Transform method is invoked, the transformer attempts to load documents through a callback. This process will definitely be streamlined so that the re-implementation of the following method isn’t required. The callback method loads the content straight from the database through an SqlContentProvider object. Not much has really changed here since Vodka 1.0 except for the addition of support for both languages and versioning.

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    public Content GetContent(string uri, int parent)
    {
        SqlContentProvider scp = new SqlContentProvider();
 
        NameValueCollection parameters = new NameValueCollection();
        parameters.Add(SqlContentProvider.ConnectionStringParameterName, connectionString);
 
        scp.Initialize(parameters);
 
        Content content = scp.GetContent(uri.ToLower());
 
        return content;
    }
 
    private XPathDocument GetDocument(Uri uri)
    {
        Content content = GetContent(uri.OriginalString, -1);
 
        XPathDocument document = new XPathDocument(new StringReader(content.Xml));
 
        return document;
    }
}

And finally the simple extension object:

?View Code CSHARP
1
2
3
4
5
6
7
public class VodkaXslExtensions
{
    public string GetDate()
    {
        return DateTime.Now.ToString();
    }
}

So what does this produce exactly? Well it takes the following XML…

1
2
3
4
5
6
7
8
9
<?xml version="1.0"?>
<content>
    <title>Home</title>
    <description>
        <p>This website is still under construction, please check back soon.</p>
        <p>Thank you,</p>
        <p><a href="http://jsedlak.com">John Sedlak</a></p>
    </description>
</content>

And uses the following XSLT file (stored in the Vodka Database)…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:test="http://focusedgames.com/vodka" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl test"
>
    <xsl:output method="xml" indent="yes"/>
 
    <xsl:template match="@* | node()">
      <h2>
        <xsl:value-of select="title"/>
      </h2>
        <div class="Description">
            <xsl:value-of select="description"/>
        </div>
        <p><xsl:value-of select="test:GetDate()"/></p>
    </xsl:template>
</xsl:stylesheet>

And produces the following HTML…

1
2
3
<h2>Home</h2> 
<div class="Description">This website is still under construction, please check back soon.Thank you,John Sedlak</div> 
<p>9/21/2009 5:23:04 PM</p>

Sitecore Tip: Stripping HTML Tags

Here is a quick and incredibly useful tip for using the Sitecore API. Recently I was looking for an easy way to strip HTML tags from a string (in C# code) and Alex de Groot responded to the call. Turns out that the process is insanely painless.

?View Code CSHARP
1
Sitecore.StringUtil.RemoveTags(string) : string

A Spark of Genius?

Knowing how frameworks are designed and developed definately has its benefits. Awhile ago I spent some time looking into how DependencyObject and DependencyProperty work in WPF. Essentially, many of the properties are not simple properties but rather facades for method invocations.

Fast forward to today when I was working on Versionator, an application I am writing to help me manage my many projects’ versions. The problem is that project information files (AssemblyInfo.cs) are not straight forward in terms of parsing. They are merely text files, awkward and malformed code files in fact. To be able to support many properties so easily, I came up with a scheme to parse, manage and save the projects’ properties in the file.

What I do is parse the properties, extracting the data and storing it in a dictionary as “old values.” At the same time I create a copy of the values in a “current values” dictionary. As new values come in, I channel them through properties, then Get and Set methods which access the “current values” dictionary. When it comes time to save I have to do some management of the data based on whether or not the property was empty, non-existant or is being changed to empty. It is simple to say that it would have taken me a lot longer if I had not taken a look at WPF. So was it a spark of genius? Or just plain old learnedness?

The Code (Beware of its massive length):

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
using System;
using System.Collections.Generic;
using System.IO;
 
namespace FocusedGames.Versionator.Data
{
    public class ProjectInfo
    {
        public enum Properties : ushort
        {
            Title = 0,
            Description = 1,
            Company = 2,
            Product = 3,
            Copyright = 4,
            Trademark = 5,
            AssemblyVersion = 6,
            FileVersion = 7,
            Guid = 8
        }
 
        private readonly string[] lookups = new [] { "AssemblyTitle", "AssemblyDescription", "AssemblyCompany", "AssemblyProduct", "AssemblyCopyright", "AssemblyTrademark", "AssemblyVersion", "AssemblyFileVersion", "Guid" };
        private readonly Dictionary<ushort, string> propertyValues = new Dictionary<ushort, string>();
        private readonly Dictionary<ushort, string> oldValues = new Dictionary<ushort, string>();
 
        public static ProjectInfo FromFile(string filename)
        {
            return new ProjectInfo(filename);
        }
 
        public ProjectInfo()
        {
            Array enumValues = Enum.GetValues(typeof (Properties));
 
            foreach(ushort prop in enumValues)
            {
                propertyValues.Add(prop, string.Empty);
                oldValues.Add(prop, string.Empty);
            }
        }
 
        public ProjectInfo(string filename)
            : this()
        {
            Load(filename);
        }
 
        #region Getting and Setting Project Properties
        protected void SetProperty(Properties prop, string value)
        {
            propertyValues[(ushort) prop] = value;
        }
 
        protected string GetProperty(Properties prop)
        {
            string newValue = propertyValues[(ushort) prop];
 
            if(string.IsNullOrEmpty(newValue))
                return oldValues[(ushort) prop];
 
            return newValue;
        }
        #endregion
 
        #region Loading and Saving
        public void Load(string filename)
        {
            Filename = filename;
 
            string[] lines = File.ReadAllLines(Filename);
 
            Array enumValues = Enum.GetValues(typeof (Properties));
 
            foreach(ushort prop in enumValues)
            {
                Load(lines, prop);
            }
        }
 
        private void Load(string[] lines, ushort lookup)
        {
            for(int i = 0; i < lines.Length; i++)
            {
                string currentLine = lines[i];
                string searchTerm = lookups[lookup];
 
                // Get the first index of the search term
                int firstIndex = currentLine.IndexOf(searchTerm);
 
                // The property wasn't found, continue
                // through the file.
                if(firstIndex == -1)
                    continue;
 
                // Now we need to extract the data out of the string!
                string data = currentLine.Substring(firstIndex + searchTerm.Length).TrimFront("\"").TrimBack("\"");
 
                oldValues[lookup] = data;
                propertyValues[lookup] = data;
            }
        }
 
        public void Save()
        {
            string[] lines = File.ReadAllLines(Filename);
 
            Array enumValues = Enum.GetValues(typeof(Properties));
 
            foreach (ushort prop in enumValues)
                Save(lines, prop);
 
            StreamWriter sw = new StreamWriter(Filename, false);
 
            for(int i = 0; i < lines.Length; i++)
                sw.WriteLine(lines[i]);
 
            sw.Close();
        }
 
        private void Save(string[] lines, ushort prop)
        {
            for (int i = 0; i < lines.Length; i++)
            {
                string currentLine = lines[i];
                string searchTerm = lookups[prop];
 
                // Get the first index of the search term
                int firstIndex = currentLine.IndexOf(searchTerm);
 
                // The property wasn't found, continue
                // through the file.
                if (firstIndex == -1)
                    continue;
 
                string oldValueLocal = oldValues[prop];
                string newValueLocal = propertyValues[prop];
 
                // If the old value didn't exist, we can adjust the 
                // replacement mechanism to remove the "" and add
                // them back in.
                if (string.IsNullOrEmpty(oldValueLocal))
                {
                    oldValueLocal = "\"\"";
                    newValueLocal = string.Format("\"{0}\"", newValueLocal);
                }
 
                // We also need to catch people emptying strings out.
                // To do this we adjust the saving mechanism the same way.
                if(string.IsNullOrEmpty(newValueLocal))
                {
                    oldValueLocal = string.Format("\"{0}\"", oldValueLocal);
                    newValueLocal = "\"\"";
                }
 
                // Replace the old value with the new value
                if (!string.IsNullOrEmpty(newValueLocal))
                        lines[i] = lines[i].Replace(oldValueLocal, newValueLocal);
            }
        }
        #endregion
 
        public string Filename { get; private set; }
 
        public string AssemblyVersion
        {
            get { return GetProperty(Properties.AssemblyVersion); }
            set { SetProperty(Properties.AssemblyVersion, value); }
        }
 
        public string FileVersion
        {
            get { return GetProperty(Properties.FileVersion); }
            set { SetProperty(Properties.FileVersion, value); }
        }
 
        public string Title 
        {
            get { return GetProperty(Properties.Title); }
            set { SetProperty(Properties.Title, value); }
        }
 
        public string Description
        {
            get { return GetProperty(Properties.Description); }
            set { SetProperty(Properties.Description, value); }
        }
 
        public string Company
        {
            get { return GetProperty(Properties.Company); }
            set { SetProperty(Properties.Company, value); }
        }
 
        public string Product 
        {
            get { return GetProperty(Properties.Product); }
            set { SetProperty(Properties.Product, value); }
        }
 
        public string Copyright
        {
            get { return GetProperty(Properties.Copyright); }
            set { SetProperty(Properties.Copyright, value); }
        }
 
        public string Trademark
        {
            get { return GetProperty(Properties.Trademark); }
            set { SetProperty(Properties.Trademark, value); }
        }
 
        public string Guid
        {
            get { return GetProperty(Properties.Guid); }
            set { SetProperty(Properties.Guid, value); }
        }
    }
}

P.S. The code is not done, is not even close to being efficient or functionally complete. But it works!

Tackling The Problem

Tackling the problem in the previous post I have decided to rely on providing more options than necessary. I have to remember that because Vodka is not client software, I have to write it as if the client software will be as simple as possible. The goal of Vodka is to give developers a way of setting up a software based CMS with great ease.

To do this, I have built in services that can be implemented and exposed via WCF as well as built in implementations of these services. If you had the binaries for Vodka, you could reference FocusedGames.Vodka.Services, create a class in a Service project and inherit from ContentService or MembershipService. After deploying the project, you can treat it like any other WCF service reference.

The original question dealt with translation services however, is it a client or server responsibility? You would generally make it client side because you may wish to get a different template for the content or change how translation is done. This is on par with most CMS software installs out there but there is a problem. Templates in the Vodka backend are treated as standard items of content. It then would require two calls to the service: one for the template and one for the content. You would also have to know how the template is extracted from the content item. This is a bad idea as it increases server load unecessarily.

The answer is simple: abstract it and keep it server side. The idea here is that the developers can plugin their own template provider into the service when setting it up. This will allow them to point to another service, a local directory or hardcoded templates. If no plugin is used, the service will continue on its standard course, grabbing the template from the standard content data store.

You may be asking why you would ever want to use a custom provider to point to a second service. Let’s say you have a ton of websites that you all want to look the same. For instance Microsoft may have microsoft.com, msdn.microsoft.com, creators.xna.com, xbox.com, et cetera and may want them to all use the same templates for items. They could use a provider to point to a single template service removing the need to change 5+ templates on 5+ servers.

Problems With Vodka

The Vodka Content Management System is a service based, multitier setup with the clients getting access to all content and member information via services. In turn, the services communicate with each other as well as their respective data stores. One of the goals of designing Vodka is to implement objects in a way that is easily extendable. To accomplish this, all content is managed in terms of the text data (XML) and its meta data (title, author, date stamps, et al).

The problem is how this data is transformed into its two main uses: HTML and .NET Objects. The question is where these transformations take place. In order to transform an XML file into HTML, the code needs access to an XSL file. The problem with this is that it too, is treated as a piece of content. It is regulated in exactly the same way with the same level of security. Thus it can be seen that this service should remain on the server. This is where it currently sits, so what is the problem?

The problem remains that it shouldn’t be a server side operation! That is slow! It requires more implementations than necessary and furthermore it builds a bad dependency on the server for specific implementation.

Screenshot of the Day

This is from the most recent build of FGF:

Aero In Xna

Yes, it is my own implementation of the Aero style of windows done in XNA. What does this mean? Well I have decided that although the simple way of doing a menu system in games is fine for simple situations, I want something more powerful and prettier to look at. Thus I have started working on a new UI library for Thrust that is based on Aero and similar interfaces. I am doing it in a fully customizable but lightweight manner and working on Xbox 360 compatibility.