Dependency Inversion Principle in WCF - wcf

I have a WCF service and I was trying following dependency Inversion Principle there. I have some queries and list below.
Code before dependency principle and after dependency principle is given below..
Code before dependency principle:-
INodeAppService.cs
namespace MyAppService
{
public class Nodes
{
[DataMember]
public int NodeID { get; set; }
[DataMember]
public string Item { get; set; }
}
[ServiceContract]
public interface INodeAppService
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
List<Nodes> GetNodes(); //changed
}
}
NodeAppService.svc.cs
namespace MyAppService
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class NodeAppService: INodeAppService
{
public List<Nodes> GetNodes()
{
List<Nodes> nodeList = new List<Nodes>(); //changed
SqlCommand sqlCommand = new SqlCommand("myquery", conn);
SqlDataAdapter da = new SqlDataAdapter(sqlCommand);
DataTable dt = new DataTable();
try
{
da.Fill(dt);
foreach (DataRow row in dt.Rows)
{
Nodes node= new Nodes();
node.NodeID = Convert.ToInt32(row["NodeID"]);
node.Item = row["Item"].ToString();
nodeList.Add(node); //changed
}
return nodeList;
}
catch (Exception e)
{
throw e;
}
finally
{
conn.Close();
}
}
Code after dependency principle :-
INodeAppService.cs
namespace MyAppService
{
public class Nodes
{
[DataMember]
public int NodeID { get; set; }
[DataMember]
public string Item { get; set; }
}
[ServiceContract]
public interface INodeAppService
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
IList<Nodes> GetNodes(); // List changed to IList
}
}
NodeAppService.svc.cs
namespace MyAppService
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class NodeAppService: INodeAppService
{
private IList<Nodes> _nodeList;
public NodeAppService(IList<Nodes> nodeList)
{
_nodeList= nodeList;
}
public IList<Nodes> GetNodes()
{
SqlCommand sqlCommand = new SqlCommand("myquery", conn);
SqlDataAdapter da = new SqlDataAdapter(sqlCommand);
DataTable dt = new DataTable();
try
{
da.Fill(dt);
foreach (DataRow row in dt.Rows)
{
Nodes node= new Nodes(); // How can I remove this dependency?
node.NodeID = Convert.ToInt32(row["NodeID"]);
node.Item = row["Item"].ToString();
_nodeList.Add(node);
}
return _nodeList;
}
catch (Exception e)
{
throw e;
}
finally
{
conn.Close();
}
}
1) But I am getting error "The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor. To fix the problem, add a default constructor to the type, or pass an instance of the type to the host".
But giving default parameter will not fix my problem. Please give a solution to solve the problem.
2) Nodes node= new Nodes(); // How can I remove this dependency? [Please see the code]
3) Dependency Inversion Principle and wcf is good approach?
Thanks.
I was able to implement Dependency Inversion Principle using the Dependency Injection Container named "Castle Windsor". But it seems like in my case creating object of Nodes class is not referred as "Dependency".
List<Nodes> nodeList = new List<Nodes>();
I have read like this .
"A data only object are not typically referred to as a "dependency", since they don't perform some needed function." Any thoughts?
Thanks.

The dependency here is your Service implementation not the specific nodes collection, Your WCF service is dependent on SQL data access code that should be abstracted and injected into the service.
Essentially the following code needs to be put in front of an interface so your WCF service no longer has this dependency
SqlCommand sqlCommand = new SqlCommand("myquery", conn);
SqlDataAdapter da = new SqlDataAdapter(sqlCommand);
DataTable dt = new DataTable();
try
{
da.Fill(dt);
foreach (DataRow row in dt.Rows)
{
Nodes node= new Nodes(); // How can I remove this dependency?
node.NodeID = Convert.ToInt32(row["NodeID"]);
node.Item = row["Item"].ToString();
_nodeList.Add(node);
}
return _nodeList;
}
catch (Exception e)
{
throw e;
}
finally
{
conn.Close();
}
The following Blog uses a repository pattern to implement dependency inversion
http://thedersen.com/blog/2010/04/20/dependency-inversion/

Related

How is raw SQL run against an Entity Framework Core context?

I have used Entity Framework for a long time, but have an edge case where I need to use SQL. I was wondering if I could use my existing Entity Framework Core context for this or not. Here is what I have currently, but the queryResults variable contains a "-1" value, instead of a list of Students, after running it:
string tableName = "Students";
var queryResults = db.Database.ExecuteSqlRaw(#"SELECT * FROM {0}", tableName);
Any ideas?
Entity Framework Core 3.1
.NET Core 3.1
Linq-to-SQL
It is possible; I just had to do this for a pet project.
You need to reference the Microsoft.EntityFrameworkCore.Relational NuGet.
ConsoleApp Example:
Program.cs
using System.Collections.Generic;
namespace EfDirectSql
{
class Program
{
/*
* written: VS2019 .Net Core 3.1 Console App
*
* used nugets:
*
* Microsoft.EntityFrameworkCore.SqlServer 3.1.0
* Microsoft.EntityFrameworkCore.Relational 3.1.0
*
*/
static void Main(string[] args)
{
// attention: supply your database server name
ApplicationContext context = new ApplicationContext("?YOURSERVER?", "Master");
// note: leveraging included extension methods for the dbContext class.
object scalarResult = context.ExecuteScalar("SELECT COUNT(1) FROM Master.dbo.SysObjects");
object nonQueryResult = context.ExecuteNonQuery("SELECT * FROM Master.dbo.SysObjects"); // likely your -1
IEnumerable<SysObject> readerResult = context.ExecuteReader<SysObject>("SELECT * FROM Master.dbo.SysObjects");
}
}
}
ApplicationContext.cs
using Microsoft.EntityFrameworkCore;
namespace EfDirectSql
{
public class ApplicationContext
: DbContext
{
public ApplicationContext(string serverName, string catalogName)
{
this.ServerName = serverName;
this.CatalogName = catalogName;
}
public readonly string ServerName;
public readonly string CatalogName;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer($"Data Source={this.ServerName};Initial Catalog={this.CatalogName};Integrated Security=true;");
base.OnConfiguring(optionsBuilder);
}
}
}
DbContextExtensions.cs
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
namespace EfDirectSql
{
public static class DbContextExtensions
{
public static object ExecuteScalar
(
this DbContext context,
string sql
)
{
IDbConnection connection = context.Database.GetDbConnection();
IDbCommand command = connection.CreateCommand();
object result = null;
try
{
connection.Open();
command.CommandText = sql;
command.CommandType = CommandType.Text;
result = command.ExecuteScalar();
}
finally
{
connection.Close();
}
return result;
}
public static int ExecuteNonQuery
(
this DbContext context,
string sql
)
{
IDbConnection connection = context.Database.GetDbConnection();
IDbCommand command = connection.CreateCommand();
int result;
try
{
connection.Open();
command.CommandText = sql;
command.CommandType = CommandType.Text;
result = command.ExecuteNonQuery();
// likely the -1
}
finally
{
connection.Close();
}
return result;
}
public static IEnumerable<TType> ExecuteReader<TType>
(
this DbContext context,
string sql
)
where TType : class, new()
{
IDbConnection connection = context.Database.GetDbConnection();
IDbCommand command = connection.CreateCommand();
IEnumerable<TType> result = new List<TType>();
try
{
connection.Open();
command.CommandText = sql;
command.CommandType = CommandType.Text;
IDataReader reader = command.ExecuteReader(CommandBehavior.Default);
result = Convert<TType>(reader);
}
finally
{
connection.Close();
}
return result;
}
private static IEnumerable<TType> Convert<TType>(IDataReader reader)
where TType : class, new()
{
List<PropertyInfo> properties = typeof(TType)
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.CanWrite)
.ToList();
IList<TType> instances = new List<TType>();
while (reader.Read())
{
TType instance = new TType();
properties
.ForEach
(p =>
// for the purposes of the example, this works - could be outliers.
p.SetValue(instance, reader[p.Name] == DBNull.Value ? null : reader[p.Name])
);
instances.Add(instance);
}
return instances;
}
}
}
SysObject.cs
namespace EfDirectSql
{
// shortened represenation of the MS-SQL sysobject table
public class SysObject
{
public string name { get; set; }
public int id { get; set; }
public string xtype { get; set; }
public int uid { get; set; }
public int info { get; set; }
public int status { get; set; }
// the rest are not needed for a demo.
}
}
"I was wondering if I could use my existing Entity Framework Core context for this or not":
Yes you can use your existing databaseContext but you have to execute that query on your dbContext Entity see the example below:
var sqlCommand = $"SELECT * FROM Students";
var executeSQL = await _context.Students.FromSqlRaw(sqlCommand).ToListAsync();
return Ok(executeSQL);
Output:
Note: As you can see I am executing sqlCommand on Students dbContext this is valid. But using DbContext you cannot pass the
table name dynamically. You must need to define it explicitly.
Hope above steps guided you accordingly, You can have a look on official document for more details here
Update Using Ado.Net Connection:
using (var connection = _context.Database.GetDbConnection())
{
connection.Open();
var tableName = "Students";
List<Student> _listStudent = new List<Student>();
var command = connection.CreateCommand();
command.CommandType = CommandType.Text;
command.CommandText = string.Format("SELECT * FROM [{0}];", tableName);
SqlDataReader reader = (SqlDataReader)command.ExecuteReader();
while (reader.Read())
{
var student = new Student(); // You have to bind dynamic property here based on your table entities
student.FirstName = reader["FirstName"].ToString(); // Remember Type Casting is required here it has to be according to database column data type
student.LastName = reader["LastName"].ToString();
_listStudent.Add(student);
}
reader.Close();
command.Dispose();
connection.Close();
}

I Cant Return List Type from Wcf

[DataContract]
public class UserDetails
{
string _userid;
string tckimlik;
string ad;
string tarih;
string aciklama;
[DataMember]
public string userid
{
get { return _userid; }
set { _userid = value; }
}
[DataMember]
public string Tckimlik
{
get { return tckimlik; }
set { tckimlik = value; }
}
[DataMember]
public string Ad
{
get { return ad; }
set { ad = value; }
}
[DataMember]
public string Tarih
{
get { return tarih; }
set { tarih = value; }
}
[DataMember]
public string Aciklama
{
get { return aciklama; }
set { aciklama = value; }
}
}
public interface IService1
{
[OperationContract]
List<UserDetails> GetAllPersons();
}
My Class DataContract and OperationContract given above.
My Method GetAllPersons type of List beloew.
public List<UserDetails> GetAllPersons()
{
List<UserDetails> userL = new List<UserDetails>();
try
{
NpgsqlConnection con = new NpgsqlConnection("");
con.Open();
NpgsqlCommand cmd = new NpgsqlCommand("SELECT * FROM RegistrationTable",con);
NpgsqlDataAdapter sda = new NpgsqlDataAdapter(cmd);
NpgsqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
UserDetails us = new UserDetails()
{
userid = reader[0].ToString(),
Tckimlik = reader[1].ToString(),
Ad = reader[2].ToString(),
Tarih = reader[3].ToString(),
Aciklama = reader[4].ToString()
};
userL.Add(us);
}
con.Close();
return userL;
}
catch (Exception)
{
throw;
}
}
The Code above is in WCF Service. I want to call GetAllPersons method in Xamarin. But i have trouble with it. My Xamarin code is below.
void getVisitor()
{
List<ServiceReference1.UserDetails> getir = new List<ServiceReference1.UserDetails>();
getir = service.GetAllPersonsAsync();
}
When i wanted to call method in service, i get an error given below.
Severity Code Description Project File Line Suppression State
Error CS0029 Cannot implicitly convert type 'System.Threading.Tasks.Task<ServiceReference1.GetAllPersonsResponse>' to 'System.Collections.Generic.List<ServiceReference1.UserDetails>' XamarinCRUD C:\Users\Eyyub\source\repos\XamarinCRUD\XamarinCRUD\XamarinCRUD\MainPage.xaml.cs 59 Active
Who can hint me, appreciate it!
Best for all!
I also checked logs and no show. Some says that WCF doesnt (de)serialize List return type. Is it true? if yes, what is the solution?. When i used same service through FormApp, works fine. But Xamarin doesnt..

When creating a WCF service, I get error: doesn't implement interface member

Error 1
'UserWcfService.userService' does not implement interface member
'UserWcfService.IuserService.Getuserdetails()'.
'UserWcfService.userService.Getuserdetails()' cannot implement an
interface member because it is not
public. C:\Users\ravi\Documents\Visual Studio
2013\Projects\wcfservices\UserWcfService\UserWcfService\userService.svc.cs 16 18 UserWcfService
userservice.svc.cs code:
namespace UserWcfService
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "userService" in code, svc and config file together.
// NOTE: In order to launch WCF Test Client for testing this service, please select userService.svc or userService.svc.cs at the Solution Explorer and start debugging.
public class userService : IuserService
{
public string str = ConfigurationManager.ConnectionStrings["connstring"].ToString();
List<usertype> Getuserdetails()
{
List<usertype> userdetails=new List<usertype>();
SqlConnection conn = new SqlConnection(str);
{
conn.Open();
SqlCommand cmd = new SqlCommand("spgetdata", conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
if (dt.Rows.Count > 0)
{
for(int i=0; i<dt.Rows.Count; i++)
{
usertype objinfo = new usertype();
objinfo.name = Convert.ToString(dt.Rows[i]["name"]);
objinfo.gender = Convert.ToString(dt.Rows[i]["gender"]);
objinfo.dateofbirth = Convert.ToDateTime(dt.Rows[i]["dateofbirth"]);
objinfo.address = Convert.ToString(dt.Rows[i]["address"]);
objinfo.contactno = Convert.ToInt32(dt.Rows[i]["contactno"]);
objinfo.mailid = Convert.ToString(dt.Rows[i]["mailid"]);
userdetails.Add(objinfo);
}
}
conn.Close();
}
return userdetails;
}
public string newuser(usertype user)
{
string strmessage;
SqlConnection conn = new SqlConnection(str);
{
conn.Open();
SqlCommand cmd = new SqlCommand("spinsert", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#C_Users_Name", user.name);
cmd.Parameters.AddWithValue("#C_Users_Gender", user.gender);
cmd.Parameters.AddWithValue("#lC_Users_DOB", user.dateofbirth);
cmd.Parameters.AddWithValue("#C_Users_Address", user.address);
cmd.Parameters.AddWithValue("#C_Users_ContactNo", user.contactno);
cmd.Parameters.AddWithValue("#C_Users_MailID", user.mailid);
//cmd.Parameters.AddWithValue("#C_Users_RegisteredDate", userinfo.date);
int result = cmd.ExecuteNonQuery();
if(result==1)
{
strmessage = user.name + "details inserted succesfully";
}
else
{
strmessage = user.name + "Details not inserted";
}
conn.Close();
}
return strmessage;
}
}
}
and IUserService code:
namespace UserWcfService
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IuserService" in both code and config file together.
[ServiceContract]
public interface IuserService
{
[OperationContract]
List<usertype> Getuserdetails();
[OperationContract]
string newuser(usertype user);
}
[DataContract]
public class usertype
{
[DataMember]
public string name { get; set; }
[DataMember]
public string gender { get; set; }
[DataMember]
public DateTime dateofbirth { get; set; }
[DataMember]
public string address { get; set; }
[DataMember]
public int contactno { get; set; }
[DataMember]
public string mailid { get; set; }
[DataMember]
public DateTime date { get; set; }
}
}
All interface methods are by default public therefore your class which dervies interface needs to be public as well.
A good way to see what you are doing wrong here is to right click on the IuserService in
public class userService : IuserService
go to implement interface -> implement interface explicitly
this will create the stub methods that are implementing your interface. you can either drop your code into those or you could adjust the methods that you have appropriately
Here is an example which built I derived using the method I described above
public class userService : IuserService
{
public string str = ConfigurationManager.ConnectionStrings["connstring"].ToString();
List<usertype> IuserService.Getuserdetails()
{
List<usertype> userdetails = new List<usertype>();
SqlConnection conn = new SqlConnection(str);
{
conn.Open();
SqlCommand cmd = new SqlCommand("spgetdata", conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
usertype objinfo = new usertype();
objinfo.name = Convert.ToString(dt.Rows[i]["name"]);
objinfo.gender = Convert.ToString(dt.Rows[i]["gender"]);
objinfo.dateofbirth = Convert.ToDateTime(dt.Rows[i]["dateofbirth"]);
objinfo.address = Convert.ToString(dt.Rows[i]["address"]);
objinfo.contactno = Convert.ToInt32(dt.Rows[i]["contactno"]);
objinfo.mailid = Convert.ToString(dt.Rows[i]["mailid"]);
userdetails.Add(objinfo);
}
}
conn.Close();
}
return userdetails;
}
public string newuser(usertype user)
{
string strmessage;
SqlConnection conn = new SqlConnection(str);
{
conn.Open();
SqlCommand cmd = new SqlCommand("spinsert", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#C_Users_Name", user.name);
cmd.Parameters.AddWithValue("#C_Users_Gender", user.gender);
cmd.Parameters.AddWithValue("#lC_Users_DOB", user.dateofbirth);
cmd.Parameters.AddWithValue("#C_Users_Address", user.address);
cmd.Parameters.AddWithValue("#C_Users_ContactNo", user.contactno);
cmd.Parameters.AddWithValue("#C_Users_MailID", user.mailid);
//cmd.Parameters.AddWithValue("#C_Users_RegisteredDate", userinfo.date);
int result = cmd.ExecuteNonQuery();
if (result == 1)
{
strmessage = user.name + "details inserted succesfully";
}
else
{
strmessage = user.name + "Details not inserted";
}
conn.Close();
}
return strmessage;
}

How to Bind Model Class in MVC

I am retrieving records from store procedure, but it does not bind data into view.
Here is ModelContext class:
namespace MyTesting.Models
{
public class TvSerialDB
{
public static string constr = ConfigurationManager.ConnectionStrings["TvSerialContext"].ConnectionString;
SqlConnection con;
SqlCommand cmd;
public IEnumerable<TVSerialByGroup> tvserialgroupby(string serialname)
{
List<TVSerialByGroup> tvserials = new List<TVSerialByGroup>();
using (con = new SqlConnection(constr))
{
cmd = new SqlCommand("pSerialListGroupBySerialName", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#SerialName", SqlDbType.VarChar, 100).Value = serialname;
con.Open();
SqlDataReader sdr = cmd.ExecuteReader();
while (sdr.Read())
{
TVSerialByGroup tvs = new TVSerialByGroup();
tvs.Series_Name = sdr["Series_Name"].ToString();
tvs.Image_Url_Big = sdr["Image_Url_Big"].ToString();
tvs.Season_No = sdr["Season_No"].ToString();
tvs.TotalEpisode = sdr["TotalEpisode"].ToString();
}
}
return tvserials;
}
}
}
Here is ModelClass:
namespace MyTesting.Models
{
public class TVSerialByGroup
{
public string Series_Name { get; set; }
public string Season_No { get; set; }
public string Image_Url_Big { get; set; }
public string TotalEpisode { get; set; }
}
}
Here is controller class:
public ActionResult ListAllSeason(string serial)
{
try
{
TvSerialDB tvcon = new TvSerialDB();
List<TVSerialByGroup> tv = tvcon.tvserialgroupby(serial).ToList();
return View(tv);
}
catch (Exception ex)
{
return Content(ex.Message);
}
}
When i run this application it does not display any record nor it gives error.
When i debug this code through breakpoint it returns rows into store procedure but in views it does not bind data.
You not adding your model instances to the collection.
while (sdr.Read())
{
TVSerialByGroup tvs = new TVSerialByGroup();
tvs.Series_Name = sdr["Series_Name"].ToString();
tvs.Image_Url_Big = sdr["Image_Url_Big"].ToString();
tvs.Season_No = sdr["Season_No"].ToString();
tvs.TotalEpisode = sdr["TotalEpisode"].ToString();
tvserials.Add(tvs); // add this
}
Side note: Since your initializing List<TVSerialByGroup>, you can make your method public List<TVSerialByGroup> tvserialgroupby(string serialname) and then you do not need .ToList(); in the ActionResult method.

What's the best way to serialize an array based on an interface in WCF?

First the code:
[ServiceContract]
public interface IWorker
{
[OperationContract]
void Process(XmlElement data);
[OperationContract]
void Update(Rule rule);
}
[DataContract]
public class Rule
{
[OperationContract]
public string Expression { get; set; }
[OperationContract]
public List<IAction> Actions { get; set; }
}
public interface IAction
{
void Execute(XmlElement data);
}
A dispatcher encodes data as xml and sends it to an IWorker instance where each expression is evaluated. When an IWorker instance evaluates an expression as true, IAction.Execute is called and the xml/data is passed.
What's the best way to serialize Rule.Actions? I've started writing a custom serializer but I'd prefer to see if there is an easier way.
Thanks.
I dont think you can use interfaces in DataContracts (someone correct me if im wrong, but i assume thats like trying to use a generic too). What I do, is have a parent class, then add the KnownType attribute. For instance
[DataContract]
public class Action
{
//members and properties
}
[DataContract]
public class SomeOtherAction:Action
{
//more implimentation
}
[DataContract]
[KnownType(typeof(SomeOtherAction))]
public class Rule
{
[DataMember]
List<Action> Actions{get;set;}
}
Now you can stuff any object that inherits from the parent Action object in to the Actions list, and it will properly serialize all their respective class properties (as long as the object is listed as a knowntype).
*I used "Action" name as an example to relate to yours, obviously Action is a keyword in .NET
Serialization is the process of converting between an object data and bytes which can be transferred over the wire. Interfaces define behavior, so by default WCF can't serialize such data. If you have the exact same assemblies on the client and the server, however, you can use the NetDataContractSerializer, which will essentially serialize (and be able to serialize) all the type information for the objects being serialized, so it can be recreated at the other side.
The code below shows how to use the NetDataContractSerializer in a service for that (based on the main example for this, the post from Aaron Skonnard at http://www.pluralsight-training.net/community/blogs/aaron/archive/2006/04/21/22284.aspx)
public class StackOverflow_6932356
{
[ServiceContract]
public interface IWorker
{
[OperationContract]
void Process(XmlElement data);
[OperationContract]
void Update(Rule rule);
}
[DataContract]
public class Rule
{
[DataMember]
public string Expression { get; set; }
[DataMember]
public List<IAction> Actions { get; set; }
}
public interface IAction
{
void Execute(XmlElement data);
}
public class Service : IWorker
{
static List<IAction> AllActions = new List<IAction>();
public void Process(XmlElement data)
{
foreach (var action in AllActions)
{
action.Execute(data);
}
}
public void Update(Rule rule)
{
AllActions = rule.Actions;
}
}
public class Action1 : IAction
{
public void Execute(XmlElement data)
{
Console.WriteLine("Executing {0} for data: {1}", this.GetType().Name, data.OuterXml);
}
}
public class Action2 : IAction
{
public void Execute(XmlElement data)
{
Console.WriteLine("Executing {0} for data: {1}", this.GetType().Name, data.OuterXml);
}
}
class NetDataContractSerializerOperationBehavior : DataContractSerializerOperationBehavior
{
public NetDataContractSerializerOperationBehavior(OperationDescription operationDescription)
: base(operationDescription) { }
public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes)
{
return new NetDataContractSerializer(name, ns);
}
public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes)
{
return new NetDataContractSerializer(name, ns);
}
}
static void ReplaceDCSOB(ServiceEndpoint endpoint)
{
foreach (var operation in endpoint.Contract.Operations)
{
for (int i = 0; i < operation.Behaviors.Count; i++)
{
if (operation.Behaviors[i] is DataContractSerializerOperationBehavior)
{
operation.Behaviors[i] = new NetDataContractSerializerOperationBehavior(operation);
break;
}
}
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(IWorker), new BasicHttpBinding(), "");
ReplaceDCSOB(endpoint);
host.Open();
Console.WriteLine("Host opened");
var factory = new ChannelFactory<IWorker>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
ReplaceDCSOB(factory.Endpoint);
var proxy = factory.CreateChannel();
proxy.Update(new Rule
{
Expression = "Expr",
Actions = new List<IAction> { new Action1(), new Action2() }
});
XmlDocument doc = new XmlDocument();
doc.LoadXml("<root><foo>bar</foo></root>");
proxy.Process(doc.DocumentElement);
((IClientChannel)proxy).Close();
factory.Close();
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}