Label Cloud

Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Tuesday, April 07, 2009

Linq to Coherence + Attributes + MetaData = Cool

First, we got the Linq Provider for Oracle Coherence

Second, we got attribute based serialization

Third, Metadata in the serialization stream

Once we put all that together, what we get is a set of very clean way of storing and querying data in Oracle Coherence.

A Coherence Linq provider now supports passing a CoherenceQueryTranslator as a parameter. I am providing a MetadataCoherenceQueryTranslator that uses getProperty method to access property originally serialized by the Generic Serializer. Here’s almost all relative .Net Code:

Person Class

[POFSerializableObject(StoreMetadata=true)]
    public class Person// : IPortableObject
    {
        [POFSerializableMember(Order=0,WriteAsType=POFWriteAsTypeEnum.Int16)]
        public int ID { get; set; }
        [POFSerializableMember(Order=1)]
        public string FirstName { get; set; }
        [POFSerializableMember(Order = 2)]
        public string LastName { get; set; }
        [POFSerializableMember(Order = 3)]
        public string Address { get; set; }
        [POFSerializableMember(Order = 4)]
        public string Title { get; set; }
        public Person()
        {
        }
    }
Add object function
INamedCache cache = CacheFactory.GetCache("dist-Person");
for (int i = 0; i < 1000; i++)
{
cache.Add(i, new Person()
{
   ID = i,
   FirstName = string.Format("First Name {0}", i),
   LastName = string.Format("LastName {0}", i),
   Address = string.Format("Address {0}" , Guid.NewGuid()) ,
   Title = i % 2  == 1 ? "Mr" : "Mrs"
   });
}

Query using Linq Query:

CoherenceQuery<Person> coherenceData =
 new CoherenceQuery<Person>(
	 new CoherenceQueryProvider(CacheFactory.GetCache("dist-Person"), 
		 new MetadataCoherenceQueryTranslator()));
string likeClause = "%8";
var people = from person in coherenceData
			 where
				(person.FirstName.Like("Test")
				 || person.LastName.Like(likeClause))
				 && person.Title == "Mrs"
			 select new { person.Title, person.ID, person.LastName };
IFilter filter = ((ICoherenceQueryable)people).Filter;
dataGridView1.DataSource = people.ToArray();

Internally, MetadataCoherenceQueryTranslator, will convert the linq query into a filter and execute the query against the Java POFGenericObject


Share/Save/Bookmark

Monday, April 06, 2009

99.9% pure .NET Coherence (100 % No Java Code Required)

Its not 100% .NET Coherence, since a developer is required to modify configuration files on the java service to specify the generic POF Serializer.

So to start: The .NET Class:

 

    [POFSerializableObject(StoreMetadata=true)]
    public class Person
    {
        [POFSerializableMember(Order=0,WriteAsType=POFWriteAsTypeEnum.Int16)]
        public int ID { get; set; }
        [POFSerializableMember(Order=1)]
        public string FirstName { get; set; }
        [POFSerializableMember(Order = 2)]
        public string LastName { get; set; }
        [POFSerializableMember(Order = 3)]
        public string Address { get; set; }
        [POFSerializableMember(Order = 4)]
        public string Title { get; set; }
        public Person()
        {
        }
        
    }

Note the StoreMetadata=true argument. When StoreMetadata is specified, Generic serializer will first first write a string array of property names. On server side, we must specify a Generic Java serializer. This is needed to be able to store objects for filtering. Here’s an interesting note. Unless filters are invoked, the object WILL NOT be deserialized on the java side. That means, Put, Get, GetAll calls without a filter, do not require Metadata to be written into the cache. Now. To specify Java Generic Serializer. Distributed Cache Configuration:

      <distributed-scheme>
      <scheme-name>dist-default</scheme-name>
      <serializer>
		<class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name>
		<init-params>
		  <init-param>
			<param-type>string</param-type>
			<param-value>custom-types-pof-config.xml</param-value>
		  </init-param>
		</init-params>
	  </serializer>
      <backing-map-scheme>
        <local-scheme/>
      </backing-map-scheme>
      <autostart>true</autostart>
    </distributed-scheme>

custom-types-pof-config.xml

<pof-config>
  <user-type-list>
    <!-- include all "standard" Coherence POF user types -->
    <include>coherence-pof-config.xml</include>
    <!-- include all application POF user types -->
    <user-type>
      <type-id>1001</type-id>
      <class-name>com.Coherence.Contrib.POF.POFGenericObject</class-name>
      <serializer>
        <class-name>com.Coherence.Contrib.POF.POFGenericSerializer</class-name>
        <init-params>
           <init-param>
             <param-type>int</param-type>
             <param-value>{type-id}</param-value>
           </init-param>
           <init-param>
            <param-type>boolean</param-type>
             <param-name>LoadMetadata</param-name>
             <param-value>true</param-value>
           </init-param>
         </init-params>        
	  </serializer>
    </user-type>
  </user-type-list>
</pof-config>

For now, you must specify a user-type for each .Net object. On the java side, the server will be using the POFGeneicSerializer, and all values in the object array indexed by the property names. A generic getProperty method is implemented to allow filtering on any property that was used in the serialization. Property evaluation is happening on the server, so only filtered data is returned.

Here’s a simple loop to add an object into the cache

INamedCache cache = CacheFactory.GetCache("dist-Person");
for (int i = 0; i < 1000; i++)
{
    cache.Add(i, new Person()
    {
       ID = i,
       FirstName = string.Format("First Name {0}", i),
       LastName = string.Format("LastName {0}", i),

       Address = string.Format("Address {0}" , Guid.NewGuid()) ,
       Title = i % 2  == 1 ? "Mr" : "Mrs"
    });
}

A cool side effect, data can be accessed from .Net and from Java code in the same fashion.


Share/Save/Bookmark

Attributes based Coherence POF Serializer

As much as I love Oracle Coherence, it is a very much a Java product. .Net has lots of cool tricks that can be used during programming, however, they are not implemented in Coherence .Net

Many .Net developers are used to using attributes to define object serialization. A Coherence Generic serializer allows a developer to specify POF Serialization using object attributes as well. Here’s a simple example

    [POFSerializableObject()]
    public class Person// : IPortableObject
    {
        [POFSerializableMember(Order=0,WriteAsType=POFWriteAsTypeEnum.Int16)]
        public int ID { get; set; }
        [POFSerializableMember(Order=1)]
        public string FirstName { get; set; }
        [POFSerializableMember(Order = 2)]
        public string LastName { get; set; }
        [POFSerializableMember(Order = 3)]
        public string Address { get; set; }
        [POFSerializableMember(Order = 4)]
        public string Title { get; set; }
        public Person()
        {
        }
        //#region IPortableObject Members
        //public void ReadExternal(IPofReader reader)
        //{
        //    ID = reader.ReadInt32(0);
        //    FirstName = reader.ReadString(1);
        //    LastName = reader.ReadString(2);
        //    Address = reader.ReadString(3);
        //    Title = reader.ReadString(4);
        //}
        //public void WriteExternal(IPofWriter writer)
        //{
        //    writer.WriteInt32(0, ID);
        //    writer.WriteString(1, FirstName);
        //    writer.WriteString(2, LastName);
        //    writer.WriteString(3, Address);
        //    writer.WriteString(4, Title);
        //}
        //#endregion
    }

To force Coherence to use the serialization attribute, use the the Coherence Generic Serializer in the POF Configuration File

    <user-type>
      <type-id>1001</type-id>
      <class-name>CoherenceSample.Person, CoherenceSample</class-name>
      <serializer>
        <class-name>Coherence.Contrib.POFGenericSerializer, Coherence.Contrib</class-name>
      </serializer>
    </user-type>

Some important points to mention:

  • Object must include POFSerializableObject attribute
  • Generic Serializer will serialize Properties and Members
  • Objects MUST NOT implement IPortableObject. Doing so will force Coherence to use ReadExternal and WriteExternal functions instead of a custom serializer
  • Order parameter of the attribute is optional. The order of serialization is Order, Alphabetical Ascending. Meaning. Multiple attributes can have the same order argument, and will be serialized in alphabetical order
  • WriteAsType parameter is optional and is usually derived based on the source type.
  • Serializer uses Converter.Convert() to convert between object types.
  • Most (but not all) main types are implemented. Check out the source code for specifics
  • Hardcoding a serializer still provides better performance due to extra boxing and object conversion performed by the serializer.

Please check out the latest code on Google Code: http://code.google.com/p/linqtocoherence

Technorati Tags: ,,,


Share/Save/Bookmark

Wednesday, March 18, 2009

Linq Provider for Oracle Coherence – Pt 2

In previous post I published about a Linq for Oracle Coherence. Linq makes it very convenient to add functionality to a provider, however creating a functionally reach and complete provider is a very complicated process.

Latest functionality I’ve added was ability to use coherence extractors in the query. Linq does not allow you to change its keywords and syntax, however, all functions are converted to linq expressions and are passed to the ExpressionVisitor for evaluation. First thing is to create an extended function to provide the functionality

public static T Extractor<T>(this object obj, string Name)
{
    throw new NotSupportedException();
}
public static T ChainedExtractor<T>(this object obj, string Name)
{
    throw new NotSupportedException();
}

The functions themselves do not have any functionality and are used solely to be converted to a linq expression. I’ve created them as Generic functions to be able to strongly type against extracted data

In the QueryTranslator class VisitMethodCall() function, we add functionality to evaluate the expression

if (m.Method.DeclaringType == typeof(LinqFunctions))
{
    if (m.Method.Name == "Extractor")
    {
        this.Visit(m.Arguments[1]);
        string right = (string)globalFilter;
        globalFilter = new Tangosol.Util.Extractor.ReflectionExtractor(right);
        return m;
    }
    else if (m.Method.Name == "ChainedExtractor")
    {
        this.Visit(m.Arguments[1]);
        string right = (string)globalFilter;
        globalFilter = new Tangosol.Util.Extractor.ChainedExtractor(right);
        return m;
    }
}

m.Arguments[0] has the reference to the parent object. m.Arguments[0] contains the argument. This allows us to create a Coherence Extractor that is used in the filters higher in the expression tree.


A Note: I hope that the project gets some visibility and comments. Oracle Coherence is an excellent product with great .NET potential. Check out the project on google code: http://code.google.com/p/linqtocoherence


Share/Save/Bookmark

Tuesday, March 17, 2009

Linq provider for Oracle Coherence (Linq to Coherence)

I am very impressed with Coherence from Oracle. Coherence provides a distributed in-memory cache and processing fabric. However it is a lot more then just a cache. It can be used for everything from messaging to cross platform communication medium. There is too much to talk say about it, so read more information at Oracle: http://www.oracle.com/technology/products/coherence/index.html

Coherence works very nicely with .Net however, in the days of Linq, I wanted to write a Linq provider for it. My code is based largely on the Linq provider documentation on MSDN (http://msdn.microsoft.com/en-us/library/bb546158.aspx) and excellent series on creating a linq provider by Matt Warren (http://blogs.msdn.com/mattwar/pages/linq-links.aspx)

I am using Google Code to host the project under Artistic License. Please check out the full source code at http://code.google.com/p/linqtocoherence/.

Below is a rundown on two main classes. The main part of the code that deals with Coherence is in two classes CoherenceQueryProvider and CoherenceQueryTranslator.

CoherenceQueryProvider accepts a connection to the INamedCache – a reference to coherence cache that will be queried.

public class CoherenceQueryProvider  : IQueryProvider
{
   public INamedCache Cache { get; set; }
   public CoherenceQueryProvider ()
    {
    }

   public CoherenceQueryProvider(INamedCache cache)
   {
       Cache = cache;
   }

In the Execute method, CoherenceQueryProvider translates the Where clause to a Coherence Filter and executes the filter against the Cache objects to return array of values.

public object Execute(Expression expression)
{
  if (Cache == null)
      throw new InvalidOperationException("Cache is not properly set");

  // Find the call to Where() and get the lambda expression predicate.
  InnermostWhereFinder whereFinder = new InnermostWhereFinder();
  MethodCallExpression whereExpression = whereFinder.GetInnermostWhere(expression);
  LambdaExpression lambdaExpression = (LambdaExpression)((UnaryExpression)(whereExpression.Arguments[1])).Operand;

  // Send the lambda expression through the partial evaluator.
  lambdaExpression = (LambdaExpression)Evaluator.PartialEval(lambdaExpression);

  IFilter filter = new CoherenceQueryTranslator().Translate(lambdaExpression);

  object[] data = Cache.GetValues(filter);
  Type elementType = TypeSystem.GetElementType(expression.Type);
  return data;
}


CoherenceQueryTranslater uses the visitor pattern to convert the Linq Expression from the where clause to Coherence Filter. Coherence filters are nested to converting one to the other is relatively simple

protected override Expression VisitBinary(BinaryExpression b)
{
  this.Visit(b.Left);
  object lastGlobal1 = globalFilter;
  this.Visit(b.Right);
  object lastGlobal2 = globalFilter;
  switch (b.NodeType)
  {
      case ExpressionType.AndAlso:
          globalFilter = new AndFilter((IFilter) lastGlobal1, (IFilter)lastGlobal2);
          break;
      case ExpressionType.OrElse:
          globalFilter = new OrFilter((IFilter) lastGlobal1, (IFilter)lastGlobal2);
          break;

There is a lot more code in the classes to handle other filters, but a lot of it is pretty repetitive. The work on the linq provider is not done and I still have to implement some of the coherence functionality. Full code and usage sample is available on google code http://code.google.com/p/linqtocoherence/

Check it out and post your comments / suggestions.


Share/Save/Bookmark

Tuesday, July 15, 2008

Simple EntityMapperTranslator

CAB defines a very clean way of defining a translator for converting objects from one type to another. A typical use for this is to convert from an "wire" object a business object and back. This is done by creating an EntityMapperTranslator. Defining two methods: BusinessToService and ServiceToBusiness. And then registering the translator in the IEntityTranslatorService.

Often, the business object identical or nearly identical to the wire object. The code below will copy every property from the SourceType to the TargetType. Of course, this can be used outside of the EntityMapperTranslator as well for the same purpose.

class TypeTranslator : EntityMapperTranslator<SourceType, TargetType>
{
    protected override TargetType BusinessToService(IEntityTranslatorService service, SourceType value)
    {
        TargetType target = new TargetType();
        foreach (PropertyInfo pi in value.GetType().GetProperties())
        {
           PropertyInfo newPi = target.GetType().GetProperty(pi.Name);
           if (newPi != null)
           {
              if (service.CanTranslate(newPi.PropertyType, pi.PropertyType))
                 newPi.SetValue(target, service.Translate(newPi.PropertyType, pi.GetValue(value, null)), null);
              else
                 newPi.SetValue(target, pi.GetValue(value, null), null);
           }
        }
        return target;
    }
}


Share/Save/Bookmark

Saturday, May 31, 2008

1st Java annoyance

For the last month I've spent as much time writing Java code as C# code. And its definitely been a great learning experiences. Even though the core languages are very much alike, and you can usually find a function in .NET that corresponds to Java and the other way around, I've spent quite a bit of time yesterday trying something that should have been completely trivial.

The Problem:

having a Date variable loadDate that includes Date and Time, create two variables startDate and endDate where StartDate is the portion of the loadDate, and endDate is the startDate + 1 day

C# Code:

DateTime loadDate = DateTime.Now; DateTime startDate = loadDate.Date; DateTime endDate = startDate.AddDays(1);

Java Code#

GregorianCalendar cal = new GregorianCalendar( loadDate.getYear() + 1900, loadDate.getMonth(), loadDate.getDate()); Date startDate = cal.getTime(); cal.add(Calendar.DATE, 1); Date endDate = cal.getTime();

Why is the Date.getYear() function returning 108 for a year 2008? What is the logic behind that? Are the Java developers afraid of running out of integer values?

Why the Calendar class supplies the clearDate() function, but no clearTime() function?

Why I can't dd Dates the way I can other classes?

Why the Calendar.add() function doesn't return a result instead of replacing the internal value, the way other classes do?

Why is this not documented in the Date class?


Share/Save/Bookmark

Thursday, January 10, 2008

Customizing SCSF Guidance Package for Modular Development

One of the requests that I've received from other developers is the ability to use SCSF for developing a module without including the shell in the solution. We develop a large number of modules independently in different groups and having the shell be a part of every module was getting to be a problem.

The only issue that I was getting with getting this to work was that SCSF guidance package would fail in ViewTemplateCS when I would right click on a folder and tried to add a new view to the project.

To solve the issue, I was made a small tweak to the source in the ViewTemplateReferenceCS.cs. (The code comes with the SCSF, however, you will have to install it separately after the SCSF is installed) The culprit is the function ContainsRequiredReferences(Project project) Specifically the call to ContainsReference(project, prjCommon.Name)

Since the common project is not in the solution, the call failed with Null Reference exception. All I had to do was to change the last line of the function to be ContainsReference(project, "Infrastructure.Interface"); Then recompile the GuidancePackage solution and place the Microsoft.Practices.SmartClientFactory.GuidancePackage.dll into the C:\Program Files\Microsoft Smart Client Factory\Guidance Package folder.


Share/Save/Bookmark

Thursday, December 20, 2007

Compiling .NET 3.5 code to .NET 2.0 Works

This is something that is totally cool. You can use Visual Studio 2008 and a lot of the new functionality and cross compile it to .NET 2.0 and run it on the older framework. For Example, You can use Var objects, Simple Property Declarations, Property Constructors, Lambda expressions

Here's an example program that can be compiled with VS 2008 to the .NET 2.0 framework

static class Program
    {
        private class Client
        {
            public string Name { get; set; }
            public string Address { get; set; }
        }

        private static List<Client> clients = new List<Client>
        {
            new Client() {Name = "Name1", Address = "Address1" },
            new Client() {Name = "Name2", Address = "Address2" },
            new Client() {Name = "Name3", Address = "Address3" },
            new Client() {Name = "Name13", Address = "Address13" },
            new Client() {Name = "Name123", Address = "Address123" }
        };

        [STAThread]
        static void Main()
        {
            List<Client> ClientsWith1 = clients.FindAll(c => c.Name.Contains("1"));
            ClientsWith1.ForEach(c =>
            {
                var NewClient = new
                {
                    Name = c.Name,
                    Address = c.Address
                };
                Console.WriteLine(NewClient.ToString());
            });
            Console.ReadKey();
        }
    }
 
Here's the output

{ Name = Name1, Address = Address1 }
{ Name = Name13, Address = Address13 }
{ Name = Name123, Address = Address123 }

And it works without .NET 3.5 installed.

For those interested, Here's a Reflected code

internal static class Program
{
    // Fields
    private static List<Client> clients;
    [CompilerGenerated]
    private static Predicate<Client> CS$<>9__CachedAnonymousMethodDelegate2;
    [CompilerGenerated]
    private static Action<Client> CS$<>9__CachedAnonymousMethodDelegate3;

    // Methods
    static Program()
    {
        List<Client> <>g__initLocal4 = new List<Client>();
        Client <>g__initLocal5 = new Client();
        <>g__initLocal5.Name = "Name1";
        <>g__initLocal5.Address = "Address1";
        <>g__initLocal4.Add(<>g__initLocal5);
        Client <>g__initLocal6 = new Client();
        <>g__initLocal6.Name = "Name2";
        <>g__initLocal6.Address = "Address2";
        <>g__initLocal4.Add(<>g__initLocal6);
        Client <>g__initLocal7 = new Client();
        <>g__initLocal7.Name = "Name3";
        <>g__initLocal7.Address = "Address3";
        <>g__initLocal4.Add(<>g__initLocal7);
        Client <>g__initLocal8 = new Client();
        <>g__initLocal8.Name = "Name13";
        <>g__initLocal8.Address = "Address13";
        <>g__initLocal4.Add(<>g__initLocal8);
        Client <>g__initLocal9 = new Client();
        <>g__initLocal9.Name = "Name123";
        <>g__initLocal9.Address = "Address123";
        <>g__initLocal4.Add(<>g__initLocal9);
        clients = <>g__initLocal4;
    }

    [STAThread]
    private static void Main()
    {
        if (CS$<>9__CachedAnonymousMethodDelegate2 == null)
        {
            CS$<>9__CachedAnonymousMethodDelegate2 = delegate (Client c) {
                return c.Name.Contains("1");
            };
        }
        if (CS$<>9__CachedAnonymousMethodDelegate3 == null)
        {
            CS$<>9__CachedAnonymousMethodDelegate3 = delegate (Client c) {
                Console.WriteLine(new { Name = c.Name, Address = c.Address }.ToString());
            };
        }
        clients.FindAll(CS$<>9__CachedAnonymousMethodDelegate2).ForEach(CS$<>9__CachedAnonymousMethodDelegate3);
        Console.ReadKey();
    }

    // Nested Types
    private class Client
    {
        // Fields
        [CompilerGenerated]
        private string <Address>k__BackingField;
        [CompilerGenerated]
        private string <Name>k__BackingField;

        // Properties
        public string Address
        {
            [CompilerGenerated]
            get
            {
                return this.<Address>k__BackingField;
            }
            [CompilerGenerated]
            set
            {
                this.<Address>k__BackingField = value;
            }
        }

        public string Name
        {
            [CompilerGenerated]
            get
            {
                return this.<Name>k__BackingField;
            }
            [CompilerGenerated]
            set
            {
                this.<Name>k__BackingField = value;
            }
        }
    }
}
 
Technorati Tags: ,,,,


Share/Save/Bookmark

Wednesday, December 05, 2007

Creating a ClickOnce Smart Client CAB Based (SCSF) application with Environment Overrides

My application is distributed via ClickOnce and a requirement is to be able to provide endpoint overrides for multiple environments. Here's what was done to create the solution


Smart Client Software Factory includes a service called EndpointCatalog. It allow for easy management of endpoints with environment overrides. Start by adding a Microsoft.Practices.SmartClient.EndpointCatalog.dll as a reference to Infrastructure.Module. Then open ModuleController class in and register the EndpointCatalog service.

private void AddServices()
{
IEndpointCatalog catalog = WorkItem.RootWorkItem.Services.Get<IEndpointCatalog>(false);
if (catalog == null)
{
IEndpointCatalogFactory catalogFactory =
new EndpointCatalogFactory("Endpoints");

catalog = catalogFactory.CreateCatalog();
WorkItem.RootWorkItem.Services.Add<IEndpointCatalog>(catalog);
}

This will read the endpoint catalog from the application.config file , section Endpoints. Here is a partial app.config

<configSections>
<section name="Endpoints" type="Microsoft.Practices.SmartClient.EndpointCatalog.Configuration.EndpointSection, Microsoft.Practices.SmartClient.EndpointCatalog" />
</configSections>

<Endpoints>
<EndpointItems>
<add Name="DataService.DataClient"
Address="http://server/DataService.svc"
UserName="default-user-name" Password="default-password" Domain="default-domain">
<NetworkItems>
<add Name="QA" Address="http://qa.server/DataService.svc"/>
<add Name="UAT" Address="http://uat.server/DataService.svc"/>
</NetworkItems>
</add>
</EndpointItems>
</Endpoints>

The endpoints section defines an endpoint, and an override for each environment. The catalog will return the override if it exists, or the original entry if it does not.

To create the WCF client, I created the following function.

T CreateWCFClient<T, Ti>()
where T : ClientBase<Ti>, new()
where Ti : class
{
try
{
T client = new T();
if (endpointCatalog.EndpointExists(typeof(T).FullName))
{
client.Endpoint.Address = new EndpointAddress
(endpointCatalog.GetAddressForEndpoint(typeof(T).FullName, Environment));
}
return client;
}
catch (Exception)
{
throw;
}
}

Add the required service to the module that will hold the function and you are almost done. The request to create the client is as follows.

_DataWebService = CreateWCFClient<DataService.DataClient, DataService.IDataClient>();

Please comment for any questions, I'll try to clarify


Share/Save/Bookmark
Directory of Computers/Tech Blogs