I am doing some Unit testing with NUnit and NSubstitute on a function that uses HttpResponse, I know you can't mock these objects so I have created interfaces to represent them and some of there properties.
I'm having trouble understanding how to create an interface for Response.Cache.VaryByHeader
// This is my HttpResponse interface
public interface IHttpResponse
{
Stream Filter { get ; set; }
IHttpCachePolicy Cache { get; set; }
void AppendHeader(string name, string value);
}
// concrete httresponse
public class HttpResponseProxy : IHttpResponse
{
private HttpResponse _httpResponse;
public Stream Filter {
get {
return _httpResponse.Filter ?? new MemoryStream();
}
set { _httpResponse.Filter = value; }
}
public IHttpCachePolicy Cache
{
get { return new HttpCachePolicyProxy(_httpResponse.Cache); }
set { }
}
public HttpResponseProxy(HttpResponse httpResponse)
{
if (httpResponse == null)
{
throw new ArgumentNullException("httpResponse");
}
_httpResponse = httpResponse;
_httpResponse.Filter = httpResponse.Filter;
}
public void AppendHeader(string name, string value)
{
_httpResponse.AppendHeader(name, value);
}
}
// HttpCachePolicy interface
public interface IHttpCachePolicy
{
IHttpCacheVaryByHeaders VaryByHeaders { get; set; }
}
// concrete HttpCachePolicy
public class HttpCachePolicyProxy : IHttpCachePolicy
{
private HttpCachePolicy _httpCachePolicy;
public HttpCachePolicyProxy(HttpCachePolicy httpCachePolicy)
{
_httpCachePolicy = httpCachePolicy;
}
public IHttpCacheVaryByHeaders VaryByHeaders
{
get { return new HttpCacheVaryByHeadersProxy(_httpCachePolicy.VaryByHeaders as HttpCacheVaryByHeaders); }
set { }
}
}
public interface IHttpCacheVaryByHeaders
{
IHttpCacheVaryByHeaders HttpCacheVaryByHeaders { get; set; }
}
public class HttpCacheVaryByHeadersProxy : IHttpCacheVaryByHeaders
{
private HttpCacheVaryByHeaders _httpCacheVaryByHeaders;
public HttpCacheVaryByHeadersProxy(HttpCacheVaryByHeaders httpCacheVaryByHeaders)
{
_httpCacheVaryByHeaders = httpCacheVaryByHeaders;
}
public IHttpCacheVaryByHeaders HttpCacheVaryByHeaders
{
get { return new HttpCacheVaryByHeadersProxy(_httpCacheVaryByHeaders); }
set { }
}
}
This is the function i am actually testing:
public static void CompressPage(IHttpRequestGetCompressionMode getCompressionMode, IHttpResponse httpResponse)
{
string supportedCompression = getCompressionMode.GetClientSupportedCompressionMode();
if (supportedCompression != HttpHeaderValues.NoCompression)
{
switch (supportedCompression)
{
case HttpHeaderValues.DeflateCompression:
httpResponse.Filter = new DeflateStream(httpResponse.Filter, CompressionMode.Compress);
break;
case HttpHeaderValues.GZipCompression:
httpResponse.Filter = new GZipStream(httpResponse.Filter, CompressionMode.Compress);
break;
}
httpResponse.AppendHeader(HttpHeaderValues.ContentEncodingHeader, supportedCompression);
// this line is where i have the problem
httpResponse.Cache.VaryByHeaders[HttpHeaderValues.AcceptEncodingHeader] = true;
}
}
I'm getting "cannot apply index to an expression of type IHttpCacheVaryByHeaders" errors.
I have the interface for the response and cache but how do I represent VaryByHeaders in an interface and then use it in a concrete class?
The error seems to suggest that IHttpCacheVaryByHeaders does not have an indexer declared (e.g. bool this[string header] { get; set; }), but rather than implementing these wrappers yourself, try the HttpResponseWrapper and other System.Web.Abstractions. This will should make testing this stuff a lot easier. :)
Related
I have a custom object with varying datatypes for each property.
I would like to be able to do something like:
public void evalCI(configurationItem CI)
{
foreach (PropertyInformation n in CI)
{
Response.Write(n.Name.ToString() + ": " + n.Value.ToString() + "</br>");
}
}
My custom object is:
public class configurationItem : IEnumerable
{
private string serial;
private string model;
private DateTime? wstart;
private DateTime? wend;
private Int32 daysLeft;
private string platform;
private string productVersion;
private string manufacturer;
private bool verificationFlag;
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator)GetEnumerator();
}
public string Serial
{
set { serial = value; }
get { return serial; }
}
public string Model
{
set { model = value; }
get { return model; }
}
public DateTime? Wstart
{
set { wstart = value; }
get { return wstart; }
}
public DateTime? Wend
{
set { wend = value; }
get { return wend; }
}
public Int32 DaysLeft
{
set { daysLeft = value; }
get { return daysLeft; }
}
public string Platform
{
set { platform = value; }
get { return platform; }
}
public string ProductVersion
{
set { productVersion = value; }
get { return productVersion; }
}
public string Manufacturer
{
set { manufacturer = value; }
get { return manufacturer; }
}
public bool VerificationFlag
{
set { verificationFlag = value; }
get { return verificationFlag; }
}
My expected output would be:
-Serial: 1234567
-Model: Mustang
-Wstart: 12/12/2005
-Wend: 12/11/2006
-DaysLeft: 0
-Platform: Car
-ProductVersion: GT
-Manufacturer: Ford
-VerificationFlag: true
At first I was getting an error that GetEnumerator() had to be implemented to use a foreach loop. The problem I keep running into is that all of the examples of Indexed Properties are of a single property with an indexable list, instead of an index for each property in the object. I was able to get intellisense to give me methods for PropertyInfo by adding:
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator)GetEnumerator();
}
However, the 2nd GetEnumerator() throws:
Compiler Error Message: CS0103: The name 'GetEnumerator' does not exist in the current context.
What am I missing here? How do I modify my object to give me the results I expect from evalCI()?
You don't need to implement IEnumerable. What you do need to do is use Reflection.
This is from memory, but I believe it would look like this:
foreach (PropertyInfo n in typeof(configurationItem).GetProperties())
{
Response.Write(string.Format("{0}: {1}<br/>", n.Name, n.GetValue(CI, null)));
}
This - the code as written - will also only give you public properties, and non-indexed properties (but it doesn't look like you have any indexed properties).
Quickly getting to the problem the mapping does not occur for the following code. Could someone explain why? or what i should do for the mapping to occur?
var parent = new Parent();
parent.ChildOne.Add(new ChildOne() { Name = "Child One" });
parent.ChildTwo.Add(new ChildTwo() { Name = "Child Two" });
AnotherParent anotherParent = new AnotherParent();
anotherParent.InjectFrom<LoopValueInjection>(parent);
Required Class are below
Anothher child one
public class AnotherChildOne
{
public string Name { get; set; }
}
Another child two
public class AnotherChildTwo
{
public string Name { get; set; }
}
Another Parent
public class AnotherParent
{
public ICollection<AnotherChildOne> ChildOne { get; set; }
public ICollection<AnotherChildTwo> ChildTwo { get; set; }
public AnotherParent()
{
ChildOne = new Collection<AnotherChildOne>();
ChildTwo = new Collection<AnotherChildTwo>();
}
}
Child Two
public class ChildTwo
{
public string Name { get; set; }
}
Child One
public class ChildOne
{
public string Name { get; set; }
}
Parent
public class Parent
{
public ICollection<ChildOne> ChildOne { get; set; }
public ICollection<ChildTwo> ChildTwo { get; set; }
public Parent()
{
ChildOne = new Collection<ChildOne>();
ChildTwo = new Collection<ChildTwo>();
}
}
I believe by default Value Injector will only inject the properties with the same name of the same type. You can get around this using a tweak to the CloneInjection sample from the Value Injector documentation as described here with this code:
public class CloneInjection : ConventionInjection
{
protected override bool Match(ConventionInfo c)
{
return c.SourceProp.Name == c.TargetProp.Name && c.SourceProp.Value != null;
}
protected override object SetValue(ConventionInfo c)
{
//for value types and string just return the value as is
if (c.SourceProp.Type.IsValueType || c.SourceProp.Type == typeof(string)
|| c.TargetProp.Type.IsValueType || c.TargetProp.Type == typeof(string))
return c.SourceProp.Value;
//handle arrays
if (c.SourceProp.Type.IsArray)
{
var arr = c.SourceProp.Value as Array;
var clone = Activator.CreateInstance(c.TargetProp.Type, arr.Length) as Array;
for (int index = 0; index < arr.Length; index++)
{
var a = arr.GetValue(index);
if (a.GetType().IsValueType || a.GetType() == typeof(string)) continue;
clone.SetValue(Activator.CreateInstance(c.TargetProp.Type.GetElementType()).InjectFrom<CloneInjection>(a), index);
}
return clone;
}
if (c.SourceProp.Type.IsGenericType)
{
//handle IEnumerable<> also ICollection<> IList<> List<>
if (c.SourceProp.Type.GetGenericTypeDefinition().GetInterfaces().Contains(typeof(IEnumerable)))
{
var t = c.TargetProp.Type.GetGenericArguments()[0];
if (t.IsValueType || t == typeof(string)) return c.SourceProp.Value;
var tlist = typeof(List<>).MakeGenericType(t);
var list = Activator.CreateInstance(tlist);
var addMethod = tlist.GetMethod("Add");
foreach (var o in c.SourceProp.Value as IEnumerable)
{
var e = Activator.CreateInstance(t).InjectFrom<CloneInjection>(o);
addMethod.Invoke(list, new[] { e }); // in 4.0 you can use dynamic and just do list.Add(e);
}
return list;
}
//unhandled generic type, you could also return null or throw
return c.SourceProp.Value;
}
//for simple object types create a new instace and apply the clone injection on it
return Activator.CreateInstance(c.TargetProp.Type)
.InjectFrom<CloneInjection>(c.SourceProp.Value);
}
}
If you include the above CloneInjection code you will want to do this:
anotherParent.InjectFrom<CloneInjection>(parent);
instead of:
anotherParent.InjectFrom<LoopValueInjection>(parent);
I Have a Base Interface Like this
public interface IHRMISBaseConnector
{
IHRMISEmployeeConnector EmployeeConnector { get ; set; }
}
And i have one more interface like this
public interface IHRMISEmployeeConnector
{
String Add(EmployeeDetails e);
Boolean Update(EmployeeDetails e);
Boolean Delete(int id);
}
I want implement IHRMISBaseConnector in this class DDWEDocumentOperations
How can i implement ? Please let me know if anybody knows it
Something like this should help you:
class FakeImplementationOfEmployeeConnector : IHRMISEmployeeConnector
{
public string Add(EmployeeDetails e)
{
//...
}
public bool Update(EmployeeDetails e)
{
//...
}
public bool Delete(int id)
{
//...
}
}
class DDWEDocumentOperations : IHRMISBaseConnector
{
IHRMISEmployeeConnector employeeConnector = new FakeImplementationOfEmployeeConnector();
public IHRMISEmployeeConnector EmployeeConnector
{
get
{
return employeeConnector;
}
set
{
employeeConnector = value;
}
}
}
Here is an example:
public class DDWEDocumentOperations : IHRMISBaseConnector
{
private IHRMISEmployeeConnector _employeeConnector;
public IHRMISEmployeeConnector EmployeeConnector
{
get { return _employeeConnector; }
set { _employeeConnector = value; }
}
}
I use a session wrapper like this:
public interface ISessionWrapper
{
// ...
CultureInfo Culture { get; set; }
}
public class SessionWrapper: ISessionWrapper
{
private T GetFromSession<T>(string key)
{
return (T)HttpContext.Current.Session[key];
}
private void SetInSession(string key, object value)
{
HttpContext.Current.Session[key] = value;
}
// ...
public CultureInfo Culture
{
get { return GetFromSession<CultureInfo>("Culture"); }
set { SetInSession("Culture", value); }
}
}
I can use this interface in my controller like this:
private readonly ISessionWrapper sessionWrapper = new SessionWrapper();
// ...
ci = new CultureInfo(langName);
sessionWrapper.Culture = ci;
But how can I access this wrapper in the view below to replace the (direct call to) session variable?
#switch (Session["Culture"].ToString())
{
case "fr":
// ...
case "uk":
// ...
}
You could make use of the base view:
public abstract class BaseViewPage : WebViewPage
{
public virtual ISessionWrapper SessionWrapper
{
get
{
return new SessionWrapper();
}
}
}
public abstract class BaseViewPage<TModel> : WebViewPage<TModel>
{
public virtual ISessionWrapper SessionWrapper
{
get
{
return new SessionWrapper();
}
}
}
your views will have access to SessionWrapper property.
Make sure to add pageBaseType="SessionWrapper" attribute to pages tag in web.config.
I want to update a log file(txt) everytime when methods in a an interface class are called?
Is there any way to do this other than writing code in every method to create log?
Here's my 30 mins. you'll have to implement the logging code somewhere so you have to create another abstraction for your code. thus an abstract class is needed. i think. this is very quick and dirty.
public interface IService<T>
{
List<T> GetAll();
bool Add(T obj);
}
then you'll need the abstract class where you'll need to implement your logging routine
public abstract class Service<T> : IService<T>
{
private void log()
{
/// TODO : do log routine here
}
public bool Add(T obj)
{
try
{
log();
return AddWithLogging(obj);
}
finally
{
log();
}
}
public List<T> GetAll()
{
try
{
log();
return GetAllWithLog();
}
finally
{
log();
}
}
protected abstract List<T> GetAllWithLog();
protected abstract bool AddWithLogging(T obj);
}
as for your concrete classes
public class EmployeeService : Service<Employee>
{
protected override List<Employee> GetAllWithLog()
{
return new List<Employee>() { new Employee() { Id = 0, Name = "test" } };
}
protected override bool AddWithLogging(Employee obj)
{
/// TODO : do add logic here
return true;
}
}
public class CompanyService : Service<Company>
{
protected override List<Company> GetAllWithLog()
{
return new List<Company>() { new Company() { Id = 0, Name = "test" } };
}
protected override bool AddWithLogging(Company obj)
{
/// TODO : do add logic here
return true;
}
}
public class Employee
{
public int Id {get;set;}
public string Name { get; set;}
}
public class Company
{
public int Id { get; set; }
public string Name { get; set; }
}
then on your implementation you can just..
static void Main(string[] args)
{
IService<Employee> employee = new EmployeeService();
List<Employee> employees = employee.GetAll();
foreach (var item in employees)
{
Console.WriteLine(item.Name);
}
IService<Company> company = new CompanyService();
List<Company> companies = company.GetAll();
foreach (var item in companies)
{
Console.WriteLine(item.Name);
}
Console.ReadLine();
}
hope this helps!
I think you would have to use Aspect Oriented Programming to achieve that. Read http://www.sharpcrafters.com/aop.net
I think you meant class (instead of interface)
Two options I can think of:
Implementing INotifyPropertyChanged which is in lines of writing code in every method
or
to adopt on of the AOP frameworks in the article http://www.codeproject.com/KB/cs/AOP_Frameworks_Rating.aspx if that is not a major leap