这是我的第一篇文章。 我在c#中相当新,我正在尝试使用结构类型的列表。
package config.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import services.security.CustomUserDetailsService;
/**
*
* @author sergio
*/
@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = CustomUserDetailsService.class)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private DefaultAuthenticationEventPublisher defaultAuthenticationEventPublisher;
@Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationEventPublisher(defaultAuthenticationEventPublisher)
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/signup").anonymous()
.antMatchers("/admin/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin().loginPage("/admin/login").permitAll()
.usernameParameter("username").passwordParameter("password")
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/admin/logout"))
.logoutSuccessUrl("/admin/login?logout")
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.csrf();
}
@Bean
public DefaultAuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
return new DefaultAuthenticationEventPublisher(applicationEventPublisher);
}
}
到目前为止,我所做的一切都使用了已知的类型(例如字符串),但对于上面示例中的列表,我不能使用任何具有正结果的函数。
目前,我们的想法是获得使用该结构类型(List)的两个列表之间的差异。 BigList将始终拥有比Small列表更多的项目,并且想法是查找在BigList中不存在的SmalList中的所有项目,考虑到Field1。理想情况下,结果可能是相同类型的列表(列表)。
这可能吗? 我已经尝试了一些我在 stackoverflow 中找到的示例,但找不到很多使用结构列表的示例,而我尝试过的示例也无效。
一个符合字符串列表的例子:
public struct MyStruct
{
public string Field1;
public string Field2;
}
List<MyStruct> BigList = new List<MyStruct> { };
List<MyStruct> SmallList = new List<MyStruct> { };
可能是一个解决方案,但我需要查看一个字段(结构的Field1)而不仅仅是一个简单的字符串。
对于那些类型的列表使用.Sort或.Contains不能获得正面结果(专门查看结构的一个字段,例如List)。
有人能帮助我吗? 那太好了!
提前致谢。 的问候,
答案 0 :(得分:2)
正如其他人所说,在你的例子中使用结构,特别是因为你是C#的新手,可能是一个错误,而不是一个真正的好主意。我建议你用类替换你的结构。
您遇到的问题是因为您使用的是您自己定义的类型,因此该比较无法正常工作,或者至少不会像您预期的那样发挥作用上班。
它不知道如何比较两个对象,并且在类的情况下,将验证它是否是相同的对象,并且在结构的情况下要么进行逐字节比较(如果struct不包含引用类型)或比较它包含的引用是否相同(如果struct包含引用类型)。
要使一切正常工作,您需要做的是覆盖班级中的Equals
方法。请参阅此MSDN文章以开始此操作:https://msdn.microsoft.com/en-us/library/336aedhh(v=vs.100).aspx。
或者,您可以为您的类型实现IEqualityComparer。如果您无法访问类实现,那么它特别有用。请查看此MSDN文章:https://msdn.microsoft.com/en-us/library/bb300779(v=vs.110).aspx
答案 1 :(得分:0)
有很多方法可以解决这个问题。这是一种非常富有表现力的方法,可以使用BigList
找到没有等效SmallList
的{{1}}元素。
Field1
注意:使用var bigListWithoutSmallList =
BigList.Where( b => !SmallList.Any( x => x.Field1 == b.Field1 ));
或class
与您的问题无关。
答案 2 :(得分:0)
一个解决方案可能是实施IEquatable<MyStruct>
class Program
{
static void Main(string[] args)
{
var smallList = new List<MyStruct>() { new MyStruct
{
Field1="1f",
Field2 ="2f"
},
new MyStruct
{
Field1="2f",
Field2 ="22f"
}};
var bigList = new List<MyStruct>() { new MyStruct
{
Field1="1f",
Field2 ="2f"
},
new MyStruct
{
Field1="3 f",
Field2 ="22f"
},new MyStruct
{
Field1="4f",
Field2 ="22f"
}
};
//find the difference
var diffList = smallList.Except(bigList);
}
public struct MyStruct:IEquatable<MyStruct>
{
public string Field1;
public string Field2;
public bool Equals(MyStruct other)
{
if (this.Field1==other.Field1 && this.Field2==other.Field2)
{
return true;
}
return false;
}
public override int GetHashCode()
{
return Field1.GetHashCode() & Field2.GetHashCode();
}
public override bool Equals(object obj)
{
return this.Equals(obj);
}
}
}
结果可能是带
的结构 new MyStruct
{
Field1="2f",
Field2 ="22f"
}};
答案 3 :(得分:0)
有一个名为MoreLINQ的开源库,为ExceptBy
提供了一个名为IEnumerable<T>
的扩展方法,可以满足您的需求。
ExceptBy
具有以下签名:
public static IEnumerable<TSource> ExceptBy<TSource, TKey>(
this IEnumerable<TSource> first,
IEnumerable<TSource> second,
Func<TSource, TKey> keySelector);
键选择器是一个将源值映射到用于比较的键值的函数,但结果仍然是TSource
的序列。
在你的情况下,它将被调用如下:
var Missing = BigList
.ExceptBy(SmallList, (item => item.fieldToCompareBy)
.ToList();
与在Contains
子句中使用Any
或Where
相比,此方法具有相当好的性能。它只需要立即迭代second
序列,并且懒惰地从first
序列流式传输结果。
答案 4 :(得分:0)
除非在结构中重写Equals,否则将起作用。诀窍是你需要在内部将其视为Nullable。
brew install node
Updating Homebrew...
To restore the stashed changes to /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core run:
'cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core && git stash pop'
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==> New Formulae
gst-rtsp-server
==> Updated Formulae
artifactory exploitdb libphonenumber node@6
aws-sdk-cpp freetds llnode nsd
babl gimme mawk openvpn
bazel gst-libav mdv rancher-cli
chromedriver heroku neofetch rancher-compose
closure-compiler jasper node riemann
devd javarepl node-build scamper
dovecot kobalt node@4 yarn
==> Deleted Formulae
pdksh
==> Downloading https://homebrew.bintray.com/bottles/node-7.2.1.sierra.bottle.ta
######################################################################## 100.0%
==> Pouring node-7.2.1.sierra.bottle.tar.gz
Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
Could not symlink share/systemtap/tapset/node.stp
Target /usr/local/share/systemtap/tapset/node.stp
already exists. You may want to remove it:
rm '/usr/local/share/systemtap/tapset/node.stp'
To force the link and overwrite all conflicting files:
brew link --overwrite node
To list all files that would be deleted:
brew link --overwrite --dry-run node
Possible conflicting files are:
/usr/local/share/systemtap/tapset/node.stp
==> Using the sandbox
==> Caveats
Please note by default only English locale support is provided. If you need
full locale support you should either rebuild with full icu:
`brew reinstall node --with-full-icu`
or add full icu data at runtime following:
https://github.com/nodejs/node/wiki/Intl#using-and-customizing-the-small-icu-build
Bash completion has been installed to:
/usr/local/etc/bash_completion.d
==> Summary
/usr/local/Cellar/node/7.2.1: 3,884 files, 45.4M
$ brew link --overwrite node
Linking /usr/local/Cellar/node/7.2.1...
Error: Could not symlink share/systemtap/tapset/node.stp
/usr/local/share/systemtap/tapset is not writable.